00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203 #include <cfg/os.h>
00204 #include <sys/types.h>
00205 #include <string.h>
00206 #include <stdlib.h>
00207 #include <errno.h>
00208
00209 #include <sys/atom.h>
00210 #include <sys/heap.h>
00211 #include <sys/thread.h>
00212 #include <sys/event.h>
00213 #include <sys/timer.h>
00214
00215 #include <net/route.h>
00216 #include <netinet/in.h>
00217 #include <netinet/ip.h>
00218 #include <netinet/icmp.h>
00219 #include <netinet/ip_icmp.h>
00220 #include <netinet/ipcsum.h>
00221 #include <sys/socket.h>
00222 #include <netinet/tcp.h>
00223 #include <stdio.h>
00224 #include <io.h>
00225 #include <memdebug.h>
00226
00227 #ifdef NUTDEBUG
00228 #include <net/netdebug.h>
00229 #endif
00230
00231 #define TICK_RATE 1
00232
00237
00238 TCPSOCKET *tcpSocketList = 0;
00240 static volatile uint16_t last_local_port = 4096;
00241
00242 static uint_fast8_t registered;
00243
00244 void NutTcpDiscardBuffers(TCPSOCKET * sock)
00245 {
00246 NETBUF *nb;
00247 while ((nb = sock->so_rx_buf) != 0) {
00248 sock->so_rx_buf = nb->nb_next;
00249 NutNetBufFree(nb);
00250 }
00251 while ((nb = sock->so_tx_nbq) != 0) {
00252 sock->so_tx_nbq = nb->nb_next;
00253 NutNetBufFree(nb);
00254 }
00255 while ((nb = sock->so_rx_nbq) != 0) {
00256 sock->so_rx_nbq = nb->nb_next;
00257 NutNetBufFree(nb);
00258 }
00259 }
00260
00261
00273 void NutTcpDestroySocket(TCPSOCKET * sock)
00274 {
00275 TCPSOCKET *sp;
00276 TCPSOCKET *volatile *spp;
00277
00278
00279
00280
00281
00282
00283 sp = tcpSocketList;
00284 spp = &tcpSocketList;
00285 while (sp) {
00286 if (sp == sock) {
00287 *spp = sp->so_next;
00288 break;
00289 }
00290 spp = &sp->so_next;
00291 sp = sp->so_next;
00292 }
00293
00294
00295
00296
00297 if (sp) {
00298 NutTcpDiscardBuffers(sock);
00299 if (sock->so_devocnt)
00300 {
00301 free(sock->so_devobuf);
00302 sock->so_devocnt = 0;
00303 }
00304 memset(sock, 0, sizeof(TCPSOCKET));
00305 free(sock);
00306 }
00307 }
00308
00323 TCPSOCKET *NutTcpFindSocket(uint16_t lport, uint16_t rport, uint32_t raddr)
00324 {
00325 TCPSOCKET *sp;
00326 TCPSOCKET *sock = 0;
00327
00328
00329
00330
00331
00332 for (sp = tcpSocketList; sp; sp = sp->so_next) {
00333 if (sp->so_local_port == lport) {
00334 if (sp->so_remote_addr == raddr && sp->so_remote_port == rport && sp->so_state != TCPS_CLOSED) {
00335 sock = sp;
00336 break;
00337 }
00338 }
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348 if (sock == 0) {
00349 for (sp = tcpSocketList; sp; sp = sp->so_next) {
00350 if (sp->so_state == TCPS_LISTEN && sp->so_local_port == lport) {
00351 sock = sp;
00352 break;
00353 }
00354 }
00355 }
00356
00357 return sock;
00358 }
00359
00360
00373 TCPSOCKET *NutTcpCreateSocket(void)
00374 {
00375 TCPSOCKET *sock = 0;
00376
00377 if (!registered) {
00378 if (NutRegisterIpHandler(IPPROTO_TCP, NutTcpInput) || NutTcpInitStateMachine()) {
00379 return NULL;
00380 }
00381 registered = 1;
00382 }
00383 if ((sock = calloc(1, sizeof(TCPSOCKET))) != 0) {
00384 sock->so_state = TCPS_CLOSED;
00385
00386
00387
00388
00389 sock->so_devtype = IFTYP_TCPSOCK;
00390 sock->so_devread = NutTcpDeviceRead;
00391 sock->so_devwrite = NutTcpDeviceWrite;
00392 #ifdef __HARVARD_ARCH__
00393 sock->so_devwrite_P = NutTcpDeviceWrite_P;
00394 #endif
00395 sock->so_devioctl = NutTcpDeviceIOCtl;
00396
00397 sock->so_tx_isn = NutGetTickCount();
00398 sock->so_tx_una = sock->so_tx_isn;
00399 sock->so_tx_nxt = sock->so_tx_isn;
00400 sock->so_rx_bsz = sock->so_rx_win = TCP_WINSIZE;
00401
00402 sock->so_mss = TCP_MSS;
00403 sock->so_rtto = 1000;
00404
00405 sock->so_next = tcpSocketList;
00406
00407 sock->so_devobsz = TCP_MSS;
00408
00409 tcpSocketList = sock;
00410 }
00411 return sock;
00412 }
00413
00433 int NutTcpSetSockOpt(TCPSOCKET * sock, int optname, CONST void *optval, int optlen)
00434 {
00435 int rc = -1;
00436
00437 if (sock == 0)
00438 return -1;
00439 switch (optname) {
00440
00441 case TCP_MAXSEG:
00442 if (optval == 0 || optlen != sizeof(uint16_t))
00443 sock->so_last_error = EINVAL;
00444 else if (sock->so_state != TCPS_CLOSED)
00445 sock->so_last_error = EISCONN;
00446 else {
00447 sock->so_mss = *((uint16_t *) optval);
00448 rc = 0;
00449 }
00450 break;
00451
00452 case SO_RCVBUF:
00453 if (optval == 0 || optlen != sizeof(uint16_t))
00454 sock->so_last_error = EINVAL;
00455 else {
00456 sock->so_rx_bsz = *((uint16_t *) optval);
00457 sock->so_rx_win = sock->so_rx_bsz;
00458 rc = 0;
00459 }
00460 break;
00461
00462 case SO_SNDTIMEO:
00463 if (optval == 0 || optlen != sizeof(uint32_t))
00464 sock->so_last_error = EINVAL;
00465 else {
00466 sock->so_write_to = *((uint32_t *) optval);
00467 rc = 0;
00468 }
00469 break;
00470
00471 case SO_RCVTIMEO:
00472 if (optval == 0 || optlen != sizeof(uint32_t))
00473 sock->so_last_error = EINVAL;
00474 else {
00475 sock->so_read_to = *((uint32_t *) optval);
00476 rc = 0;
00477 }
00478 break;
00479
00480 case SO_SNDBUF:
00481 if (optval == 0 || optlen != sizeof(uint16_t))
00482 sock->so_last_error = EINVAL;
00483 else {
00484 NutTcpDeviceWrite(sock, 0, 0);
00485 sock->so_devobsz = *((uint16_t *) optval);
00486 rc = 0;
00487 }
00488 break;
00489
00490 default:
00491 sock->so_last_error = ENOPROTOOPT;
00492 break;
00493 }
00494 return rc;
00495 }
00496
00516 int NutTcpGetSockOpt(TCPSOCKET * sock, int optname, void *optval, int optlen)
00517 {
00518 int rc = -1;
00519
00520 if (sock == 0)
00521 return -1;
00522 switch (optname) {
00523
00524 case TCP_MAXSEG:
00525 if (optval == 0 || optlen != sizeof(uint16_t))
00526 sock->so_last_error = EINVAL;
00527 else {
00528 *((uint16_t *) optval) = sock->so_mss;
00529 rc = 0;
00530 }
00531 break;
00532
00533 case SO_RCVBUF:
00534 if (optval == 0 || optlen != sizeof(uint16_t))
00535 sock->so_last_error = EINVAL;
00536 else {
00537 *((uint16_t *) optval) = sock->so_rx_bsz;
00538 rc = 0;
00539 }
00540 break;
00541
00542 case SO_SNDTIMEO:
00543 if (optval == 0 || optlen != sizeof(uint32_t))
00544 sock->so_last_error = EINVAL;
00545 else {
00546 *((uint32_t *) optval) = sock->so_write_to;
00547 rc = 0;
00548 }
00549 break;
00550
00551 case SO_RCVTIMEO:
00552 if (optval == 0 || optlen != sizeof(uint32_t))
00553 sock->so_last_error = EINVAL;
00554 else {
00555 *((uint32_t *) optval) = sock->so_read_to;
00556 rc = 0;
00557 }
00558 break;
00559
00560 case SO_SNDBUF:
00561 if (optval == 0 || optlen != sizeof(uint16_t))
00562 sock->so_last_error = EINVAL;
00563 else {
00564 *((uint16_t *) optval) = sock->so_devobsz;
00565 rc = 0;
00566 }
00567 break;
00568 default:
00569 sock->so_last_error = ENOPROTOOPT;
00570 break;
00571 }
00572 return rc;
00573 }
00574
00593 int NutTcpConnect(TCPSOCKET * sock, uint32_t addr, uint16_t port)
00594 {
00595 TCPSOCKET *sp;
00596 NUTDEVICE *dev;
00597
00598 if (sock == 0)
00599 return -1;
00600
00601
00602
00603
00604 if (sock->so_state == TCPS_LISTEN) {
00605 sock->so_last_error = EOPNOTSUPP;
00606 return -1;
00607 } else if (sock->so_state != TCPS_CLOSED) {
00608 sock->so_last_error = EISCONN;
00609 return -1;
00610 }
00611
00612
00613
00614
00615 do {
00616 if (++last_local_port == 0)
00617 last_local_port = 4096;
00618
00619 sp = tcpSocketList;
00620 while (sp) {
00621
00622 if (sp->so_local_port == htons(last_local_port))
00623 break;
00624 sp = sp->so_next;
00625 }
00626 } while (sp);
00627
00628
00629
00630
00631
00632 sock->so_local_port = htons(last_local_port);
00633 sock->so_remote_port = htons(port);
00634 sock->so_remote_addr = addr;
00635
00636
00637
00638
00639 if ((dev = NutIpRouteQuery(addr, 0)) != 0) {
00640 IFNET *nif = dev->dev_icb;
00641 sock->so_local_addr = nif->if_local_ip;
00642 } else {
00643 sock->so_last_error = EHOSTUNREACH;
00644 return -1;
00645 }
00646
00647
00648
00649
00650
00651 return NutTcpStateActiveOpenEvent(sock);
00652 }
00653
00669 int NutTcpAccept(TCPSOCKET * sock, uint16_t port)
00670 {
00671 sock->so_local_port = htons(port);
00672
00673 return NutTcpStatePassiveOpenEvent(sock);
00674 }
00675
00692 int NutTcpSend(TCPSOCKET * sock, CONST void *data, int len)
00693 {
00694 uint16_t unacked;
00695
00696
00697
00698
00699 NutThreadYield();
00700
00701 if (sock == 0)
00702 return -1;
00703 if (data == 0 || len == 0)
00704 return 0;
00705
00706
00707
00708
00709 if (len > sock->so_mss)
00710 len = sock->so_mss;
00711
00712 for (;;) {
00713
00714
00715
00716 if (sock->so_state != TCPS_ESTABLISHED) {
00717 sock->so_last_error = ENOTCONN;
00718 return -1;
00719 }
00720
00721
00722
00723
00724
00725
00726 unacked = sock->so_tx_nxt - sock->so_tx_una;
00727 if ((unacked >> 2) < sock->so_mss && len <= sock->so_tx_win - unacked) {
00728 break;
00729 }
00730 if (NutEventWait(&sock->so_tx_tq, sock->so_write_to)) {
00731 return 0;
00732 }
00733 }
00734
00735
00736
00737
00738
00739 sock->so_tx_flags |= SO_ACK;
00740 if (NutTcpOutput(sock, data, len))
00741 return -1;
00742 return len;
00743 }
00744
00762 int NutTcpReceive(TCPSOCKET * sock, void *data, int size)
00763 {
00764 int i;
00765
00766 NutThreadYield();
00767
00768
00769
00770 if (sock == 0)
00771 return -1;
00772 if (sock->so_state != TCPS_ESTABLISHED && sock->so_state != TCPS_CLOSE_WAIT) {
00773 sock->so_last_error = ENOTCONN;
00774 return -1;
00775 }
00776 if (data == 0 || size == 0)
00777 return 0;
00778
00779
00780
00781
00782
00783 while (sock->so_rx_cnt - sock->so_rd_cnt == 0) {
00784 if (sock->so_state != TCPS_ESTABLISHED) {
00785 sock->so_last_error = ENOTCONN;
00786 return -1;
00787 }
00788 if (NutEventWait(&sock->so_rx_tq, sock->so_read_to))
00789 return 0;
00790 }
00791
00792 if (size > sock->so_rx_cnt - sock->so_rd_cnt)
00793 size = sock->so_rx_cnt - sock->so_rd_cnt;
00794 if (size) {
00795 NETBUF *nb;
00796 uint16_t rd_cnt;
00797 uint16_t nb_cnt;
00798 uint16_t ab_cnt;
00799 uint16_t mv_cnt;
00800
00801 rd_cnt = sock->so_rd_cnt;
00802
00803 ab_cnt = 0;
00804 while (ab_cnt < size) {
00805 nb = sock->so_rx_buf;
00806 nb_cnt = nb->nb_ap.sz - rd_cnt;
00807 mv_cnt = size - ab_cnt;
00808 if (mv_cnt > nb_cnt)
00809 mv_cnt = nb_cnt;
00810 memcpy((char *) data + ab_cnt, (char *) (nb->nb_ap.vp) + rd_cnt, mv_cnt);
00811 ab_cnt += mv_cnt;
00812 rd_cnt += mv_cnt;
00813 if (mv_cnt >= nb_cnt) {
00814 sock->so_rx_buf = nb->nb_next;
00815 sock->so_rx_cnt -= rd_cnt;
00816 NutNetBufFree(nb);
00817 sock->so_rx_apc--;
00818 nb = sock->so_rx_buf;
00819 rd_cnt = 0;
00820 }
00821 }
00822 sock->so_rd_cnt = rd_cnt;
00823
00824
00825
00826
00827 if (sock->so_state == TCPS_ESTABLISHED) {
00828 i = sock->so_rx_win;
00829 if ((i += size) > sock->so_rx_bsz)
00830 i = sock->so_rx_bsz;
00831
00832 if (sock->so_rx_win <= sock->so_mss && i > sock->so_mss) {
00833 sock->so_rx_win = i;
00834 NutTcpStateWindowEvent(sock);
00835 } else {
00836 sock->so_rx_win = i;
00837 }
00838 }
00839 }
00840 return size;
00841 }
00842
00855 int NutTcpCloseSocket(TCPSOCKET * sock)
00856 {
00857
00858
00859 NutTcpDeviceWrite(sock, 0, 0);
00860 return NutTcpStateCloseEvent(sock);
00861 }
00862
00911 int NutTcpError(TCPSOCKET * sock)
00912 {
00913 if (sock == 0)
00914 return ENOTSOCK;
00915 return sock->so_last_error;
00916 }
00917
00937 int NutTcpDeviceRead(TCPSOCKET * sock, void *buffer, int size)
00938 {
00939 return NutTcpReceive(sock, buffer, size);
00940 }
00941
00942 static int SendBuffer(TCPSOCKET * sock, CONST void *buffer, int size)
00943 {
00944 int rc;
00945 int bite;
00946
00947 for (rc = 0; rc < size; rc += bite) {
00948 if ((bite = NutTcpSend(sock, (uint8_t *) buffer + rc, size - rc)) <= 0) {
00949 return -1;
00950 }
00951 }
00952 return rc;
00953 }
00954
00977 int NutTcpDeviceWrite(TCPSOCKET * sock, CONST void *buf, int size)
00978 {
00979 int rc;
00980 uint16_t sz;
00981
00982 uint8_t *buffer = (uint8_t*) buf;
00983
00984
00985
00986
00987 if (sock == 0)
00988 return -1;
00989 if (sock->so_state != TCPS_ESTABLISHED) {
00990 sock->so_last_error = ENOTCONN;
00991 return -1;
00992 }
00993
00994
00995 if (size == 0) {
00996 if (sock->so_devocnt) {
00997 if (SendBuffer(sock, sock->so_devobuf, sock->so_devocnt) < 0) {
00998 free(sock->so_devobuf);
00999 sock->so_devocnt = 0;
01000 return -1;
01001 }
01002 free(sock->so_devobuf);
01003 sock->so_devocnt = 0;
01004 }
01005 return 0;
01006 }
01007
01008
01009 if (sock->so_devocnt == 0) {
01010
01011
01012
01013
01014 if ((uint16_t) size >= sock->so_devobsz) {
01015 rc = size % sock->so_devobsz;
01016 if (SendBuffer(sock, buffer, size - rc) < 0)
01017 return -1;
01018 buffer += size - rc;
01019 } else
01020 rc = size;
01021
01022
01023
01024
01025 if (rc) {
01026 if (!(sock->so_devobuf = malloc(sock->so_devobsz)))
01027 return -1;
01028 memcpy(sock->so_devobuf, buffer, rc);
01029 sock->so_devocnt = rc;
01030 }
01031 return size;
01032 }
01033
01034
01035 if (sock->so_devocnt + size < sock->so_devobsz) {
01036 memcpy(sock->so_devobuf + sock->so_devocnt, buffer, size);
01037 sock->so_devocnt += size;
01038 return size;
01039 }
01040
01041
01042
01043
01044 sz = sock->so_devobsz - sock->so_devocnt;
01045 memcpy(sock->so_devobuf + sock->so_devocnt, buffer, sz);
01046 buffer += sz;
01047 if (SendBuffer(sock, sock->so_devobuf, sock->so_devobsz) < 0) {
01048 free(sock->so_devobuf);
01049 sock->so_devocnt = 0;
01050 return -1;
01051 }
01052
01053
01054
01055
01056
01057 sz = size - sz;
01058 if (sz >= sock->so_devobsz) {
01059 rc = size % sock->so_devobsz;
01060 if (SendBuffer(sock, buffer, sz - rc) < 0) {
01061 free(sock->so_devobuf);
01062 sock->so_devocnt = 0;
01063 return -1;
01064 }
01065 buffer += sz - rc;
01066 } else
01067 rc = sz;
01068
01069
01070
01071 if (rc)
01072 memcpy(sock->so_devobuf, buffer, rc);
01073 else
01074 free(sock->so_devobuf);
01075 sock->so_devocnt = rc;
01076
01077 return size;
01078 }
01079
01104 #ifdef __HARVARD_ARCH__
01105 int NutTcpDeviceWrite_P(TCPSOCKET * sock, PGM_P buffer, int size)
01106 {
01107 int rc;
01108 char *rp = 0;
01109
01110
01111
01112
01113
01114 if (size && (rp = NutHeapAlloc(size)) != 0)
01115 memcpy_P(rp, buffer, size);
01116 rc = NutTcpDeviceWrite(sock, rp, size);
01117 if (rp)
01118 NutHeapFree(rp);
01119
01120 return rc;
01121 }
01122 #endif
01123
01143 int NutTcpDeviceIOCtl(TCPSOCKET * sock, int cmd, void *param)
01144 {
01145 uint32_t *lvp = (uint32_t *) param;
01146 int rc = 0;
01147
01148 switch (cmd) {
01149 case IOCTL_GETFILESIZE:
01150 case IOCTL_GETINBUFCOUNT:
01151 *lvp = (sock->so_rx_cnt - sock->so_rd_cnt);
01152 break;
01153 case IOCTL_GETOUTBUFCOUNT:
01154 *lvp = (sock->so_devocnt);
01155 break;
01156 default:
01157 rc = -1;
01158 }
01159
01160 return rc;
01161 }
01162