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 #include <cfg/os.h>
00201 #include <sys/types.h>
00202 #include <string.h>
00203 #include <stdlib.h>
00204
00205 #include <sys/atom.h>
00206 #include <sys/heap.h>
00207 #include <sys/thread.h>
00208 #include <sys/event.h>
00209 #include <sys/timer.h>
00210
00211 #include <net/errno.h>
00212 #include <net/route.h>
00213 #include <netinet/in.h>
00214 #include <netinet/ip.h>
00215 #include <netinet/icmp.h>
00216 #include <netinet/ip_icmp.h>
00217 #include <netinet/ipcsum.h>
00218 #include <sys/socket.h>
00219 #include <netinet/tcp.h>
00220 #include <stdio.h>
00221 #include <io.h>
00222 #include <memdebug.h>
00223
00224 #ifdef NUTDEBUG
00225 #include <net/netdebug.h>
00226 #endif
00227
00228 #define TICK_RATE 1
00229
00234
00235 TCPSOCKET *tcpSocketList = 0;
00237 static volatile uint16_t last_local_port = 4096;
00238
00239 static uint_fast8_t registered;
00240
00241 void NutTcpDiscardBuffers(TCPSOCKET * sock)
00242 {
00243 NETBUF *nb;
00244 while ((nb = sock->so_rx_buf) != 0) {
00245 sock->so_rx_buf = nb->nb_next;
00246 NutNetBufFree(nb);
00247 }
00248 while ((nb = sock->so_tx_nbq) != 0) {
00249 sock->so_tx_nbq = nb->nb_next;
00250 NutNetBufFree(nb);
00251 }
00252 while ((nb = sock->so_rx_nbq) != 0) {
00253 sock->so_rx_nbq = nb->nb_next;
00254 NutNetBufFree(nb);
00255 }
00256 }
00257
00258
00270 void NutTcpDestroySocket(TCPSOCKET * sock)
00271 {
00272 TCPSOCKET *sp;
00273 TCPSOCKET *volatile *spp;
00274
00275
00276
00277
00278
00279
00280 sp = tcpSocketList;
00281 spp = &tcpSocketList;
00282 while (sp) {
00283 if (sp == sock) {
00284 *spp = sp->so_next;
00285 break;
00286 }
00287 spp = &sp->so_next;
00288 sp = sp->so_next;
00289 }
00290
00291
00292
00293
00294 if (sp) {
00295 NutTcpDiscardBuffers(sock);
00296 if (sock->so_devocnt)
00297 {
00298 free(sock->so_devobuf);
00299 sock->so_devocnt = 0;
00300 }
00301 memset(sock, 0, sizeof(TCPSOCKET));
00302 free(sock);
00303 }
00304 }
00305
00320 TCPSOCKET *NutTcpFindSocket(uint16_t lport, uint16_t rport, uint32_t raddr)
00321 {
00322 TCPSOCKET *sp;
00323 TCPSOCKET *sock = 0;
00324
00325
00326
00327
00328
00329 for (sp = tcpSocketList; sp; sp = sp->so_next) {
00330 if (sp->so_local_port == lport) {
00331 if (sp->so_remote_addr == raddr && sp->so_remote_port == rport && sp->so_state != TCPS_CLOSED) {
00332 sock = sp;
00333 break;
00334 }
00335 }
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345 if (sock == 0) {
00346 for (sp = tcpSocketList; sp; sp = sp->so_next) {
00347 if (sp->so_state == TCPS_LISTEN && sp->so_local_port == lport) {
00348 sock = sp;
00349 break;
00350 }
00351 }
00352 }
00353
00354 return sock;
00355 }
00356
00357
00372 TCPSOCKET *NutTcpCreateSocket(void)
00373 {
00374 TCPSOCKET *sock = 0;
00375
00376 if (!registered) {
00377 if (NutRegisterIpHandler(IPPROTO_TCP, NutTcpInput) || NutTcpInitStateMachine()) {
00378 return NULL;
00379 }
00380 registered = 1;
00381 }
00382 if ((sock = calloc(1, sizeof(TCPSOCKET))) != 0) {
00383 sock->so_state = TCPS_CLOSED;
00384
00385
00386
00387
00388 sock->so_devtype = IFTYP_TCPSOCK;
00389 sock->so_devread = NutTcpDeviceRead;
00390 sock->so_devwrite = NutTcpDeviceWrite;
00391 #ifdef __HARVARD_ARCH__
00392 sock->so_devwrite_P = NutTcpDeviceWrite_P;
00393 #endif
00394 sock->so_devioctl = NutTcpDeviceIOCtl;
00395
00396 sock->so_tx_isn = NutGetTickCount();
00397 sock->so_tx_una = sock->so_tx_isn;
00398 sock->so_tx_nxt = sock->so_tx_isn;
00399 sock->so_rx_bsz = sock->so_rx_win = TCP_WINSIZE;
00400
00401 sock->so_mss = TCP_MSS;
00402 sock->so_rtto = 1000;
00403
00404 sock->so_next = tcpSocketList;
00405
00406 sock->so_devobsz = TCP_MSS;
00407
00408 tcpSocketList = sock;
00409 }
00410 return sock;
00411 }
00412
00432 int NutTcpSetSockOpt(TCPSOCKET * sock, int optname, CONST void *optval, int optlen)
00433 {
00434 int rc = -1;
00435
00436 if (sock == 0)
00437 return -1;
00438 switch (optname) {
00439
00440 case TCP_MAXSEG:
00441 if (optval == 0 || optlen != sizeof(uint16_t))
00442 sock->so_last_error = EINVAL;
00443 else if (sock->so_state != TCPS_CLOSED)
00444 sock->so_last_error = EISCONN;
00445 else {
00446 sock->so_mss = *((uint16_t *) optval);
00447 rc = 0;
00448 }
00449 break;
00450
00451 case SO_RCVBUF:
00452 if (optval == 0 || optlen != sizeof(uint16_t))
00453 sock->so_last_error = EINVAL;
00454 else {
00455 sock->so_rx_bsz = *((uint16_t *) optval);
00456 sock->so_rx_win = sock->so_rx_bsz;
00457 rc = 0;
00458 }
00459 break;
00460
00461 case SO_SNDTIMEO:
00462 if (optval == 0 || optlen != sizeof(uint32_t))
00463 sock->so_last_error = EINVAL;
00464 else {
00465 sock->so_write_to = *((uint32_t *) optval);
00466 rc = 0;
00467 }
00468 break;
00469
00470 case SO_RCVTIMEO:
00471 if (optval == 0 || optlen != sizeof(uint32_t))
00472 sock->so_last_error = EINVAL;
00473 else {
00474 sock->so_read_to = *((uint32_t *) optval);
00475 rc = 0;
00476 }
00477 break;
00478
00479 case SO_SNDBUF:
00480 if (optval == 0 || optlen != sizeof(uint16_t))
00481 sock->so_last_error = EINVAL;
00482 else {
00483 NutTcpDeviceWrite(sock, 0, 0);
00484 sock->so_devobsz = *((uint16_t *) optval);
00485 rc = 0;
00486 }
00487 break;
00488
00489 default:
00490 sock->so_last_error = ENOPROTOOPT;
00491 break;
00492 }
00493 return rc;
00494 }
00495
00515 int NutTcpGetSockOpt(TCPSOCKET * sock, int optname, void *optval, int optlen)
00516 {
00517 int rc = -1;
00518
00519 if (sock == 0)
00520 return -1;
00521 switch (optname) {
00522
00523 case TCP_MAXSEG:
00524 if (optval == 0 || optlen != sizeof(uint16_t))
00525 sock->so_last_error = EINVAL;
00526 else {
00527 *((uint16_t *) optval) = sock->so_mss;
00528 rc = 0;
00529 }
00530 break;
00531
00532 case SO_RCVBUF:
00533 if (optval == 0 || optlen != sizeof(uint16_t))
00534 sock->so_last_error = EINVAL;
00535 else {
00536 *((uint16_t *) optval) = sock->so_rx_bsz;
00537 rc = 0;
00538 }
00539 break;
00540
00541 case SO_SNDTIMEO:
00542 if (optval == 0 || optlen != sizeof(uint32_t))
00543 sock->so_last_error = EINVAL;
00544 else {
00545 *((uint32_t *) optval) = sock->so_write_to;
00546 rc = 0;
00547 }
00548 break;
00549
00550 case SO_RCVTIMEO:
00551 if (optval == 0 || optlen != sizeof(uint32_t))
00552 sock->so_last_error = EINVAL;
00553 else {
00554 *((uint32_t *) optval) = sock->so_read_to;
00555 rc = 0;
00556 }
00557 break;
00558
00559 case SO_SNDBUF:
00560 if (optval == 0 || optlen != sizeof(uint16_t))
00561 sock->so_last_error = EINVAL;
00562 else {
00563 *((uint16_t *) optval) = sock->so_devobsz;
00564 rc = 0;
00565 }
00566 break;
00567 default:
00568 sock->so_last_error = ENOPROTOOPT;
00569 break;
00570 }
00571 return rc;
00572 }
00573
00592 int NutTcpConnect(TCPSOCKET * sock, uint32_t addr, uint16_t port)
00593 {
00594 TCPSOCKET *sp;
00595 NUTDEVICE *dev;
00596
00597 if (sock == 0)
00598 return -1;
00599
00600
00601
00602
00603 if (sock->so_state == TCPS_LISTEN) {
00604 sock->so_last_error = EOPNOTSUPP;
00605 return -1;
00606 } else if (sock->so_state != TCPS_CLOSED) {
00607 sock->so_last_error = EISCONN;
00608 return -1;
00609 }
00610
00611
00612
00613
00614 do {
00615 if (++last_local_port == 0)
00616 last_local_port = 4096;
00617
00618 sp = tcpSocketList;
00619 while (sp) {
00620
00621 if (sp->so_local_port == htons(last_local_port))
00622 break;
00623 sp = sp->so_next;
00624 }
00625 } while (sp);
00626
00627
00628
00629
00630
00631 sock->so_local_port = htons(last_local_port);
00632 sock->so_remote_port = htons(port);
00633 sock->so_remote_addr = addr;
00634
00635
00636
00637
00638 if ((dev = NutIpRouteQuery(addr, 0)) != 0) {
00639 IFNET *nif = dev->dev_icb;
00640 sock->so_local_addr = nif->if_local_ip;
00641 } else {
00642 sock->so_last_error = EHOSTUNREACH;
00643 return -1;
00644 }
00645
00646
00647
00648
00649
00650 return NutTcpStateActiveOpenEvent(sock);
00651 }
00652
00668 int NutTcpAccept(TCPSOCKET * sock, uint16_t port)
00669 {
00670 sock->so_local_port = htons(port);
00671
00672 return NutTcpStatePassiveOpenEvent(sock);
00673 }
00674
00691 int NutTcpSend(TCPSOCKET * sock, CONST void *data, int len)
00692 {
00693 uint16_t unacked;
00694
00695
00696
00697
00698 NutThreadYield();
00699
00700 if (sock == 0)
00701 return -1;
00702 if (data == 0 || len == 0)
00703 return 0;
00704
00705
00706
00707
00708 if (len > sock->so_mss)
00709 len = sock->so_mss;
00710
00711 for (;;) {
00712
00713
00714
00715 if (sock->so_state != TCPS_ESTABLISHED) {
00716 sock->so_last_error = ENOTCONN;
00717 return -1;
00718 }
00719
00720
00721
00722
00723
00724
00725 unacked = sock->so_tx_nxt - sock->so_tx_una;
00726 if ((unacked >> 2) < sock->so_mss && len <= sock->so_tx_win - unacked) {
00727 break;
00728 }
00729 if (NutEventWait(&sock->so_tx_tq, sock->so_write_to)) {
00730 return 0;
00731 }
00732 }
00733
00734
00735
00736
00737
00738 sock->so_tx_flags |= SO_ACK;
00739 if (NutTcpOutput(sock, data, len))
00740 return -1;
00741 return len;
00742 }
00743
00761 int NutTcpReceive(TCPSOCKET * sock, void *data, int size)
00762 {
00763 int i;
00764
00765 NutThreadYield();
00766
00767
00768
00769 if (sock == 0)
00770 return -1;
00771 if (sock->so_state != TCPS_ESTABLISHED && sock->so_state != TCPS_CLOSE_WAIT) {
00772 sock->so_last_error = ENOTCONN;
00773 return -1;
00774 }
00775 if (data == 0 || size == 0)
00776 return 0;
00777
00778
00779
00780
00781
00782 while (sock->so_rx_cnt - sock->so_rd_cnt == 0) {
00783 if (sock->so_state != TCPS_ESTABLISHED) {
00784 sock->so_last_error = ENOTCONN;
00785 return -1;
00786 }
00787 if (NutEventWait(&sock->so_rx_tq, sock->so_read_to))
00788 return 0;
00789 }
00790
00791 if (size > sock->so_rx_cnt - sock->so_rd_cnt)
00792 size = sock->so_rx_cnt - sock->so_rd_cnt;
00793 if (size) {
00794 NETBUF *nb;
00795 uint16_t rd_cnt;
00796 uint16_t nb_cnt;
00797 uint16_t ab_cnt;
00798 uint16_t mv_cnt;
00799
00800 rd_cnt = sock->so_rd_cnt;
00801
00802 ab_cnt = 0;
00803 while (ab_cnt < size) {
00804 nb = sock->so_rx_buf;
00805 nb_cnt = nb->nb_ap.sz - rd_cnt;
00806 mv_cnt = size - ab_cnt;
00807 if (mv_cnt > nb_cnt)
00808 mv_cnt = nb_cnt;
00809 memcpy((char *) data + ab_cnt, (char *) (nb->nb_ap.vp) + rd_cnt, mv_cnt);
00810 ab_cnt += mv_cnt;
00811 rd_cnt += mv_cnt;
00812 if (mv_cnt >= nb_cnt) {
00813 sock->so_rx_buf = nb->nb_next;
00814 sock->so_rx_cnt -= rd_cnt;
00815 NutNetBufFree(nb);
00816 nb = sock->so_rx_buf;
00817 rd_cnt = 0;
00818 }
00819 }
00820 sock->so_rd_cnt = rd_cnt;
00821
00822
00823
00824
00825 if (sock->so_state == TCPS_ESTABLISHED) {
00826 i = sock->so_rx_win;
00827 if ((i += size) > sock->so_rx_bsz)
00828 i = sock->so_rx_bsz;
00829
00830 if (sock->so_rx_win <= sock->so_mss && i > sock->so_mss) {
00831 sock->so_rx_win = i;
00832 NutTcpStateWindowEvent(sock);
00833 } else {
00834 sock->so_rx_win = i;
00835 }
00836 }
00837 }
00838 return size;
00839 }
00840
00853 int NutTcpCloseSocket(TCPSOCKET * sock)
00854 {
00855
00856
00857 NutTcpDeviceWrite(sock, 0, 0);
00858 return NutTcpStateCloseEvent(sock);
00859 }
00860
00909 int NutTcpError(TCPSOCKET * sock)
00910 {
00911 if (sock == 0)
00912 return ENOTSOCK;
00913 return sock->so_last_error;
00914 }
00915
00935 int NutTcpDeviceRead(TCPSOCKET * sock, void *buffer, int size)
00936 {
00937 return NutTcpReceive(sock, buffer, size);
00938 }
00939
00940 static int SendBuffer(TCPSOCKET * sock, CONST void *buffer, int size)
00941 {
00942 int rc;
00943 int bite;
00944
00945 for (rc = 0; rc < size; rc += bite) {
00946 if ((bite = NutTcpSend(sock, (uint8_t *) buffer + rc, size - rc)) <= 0) {
00947 return -1;
00948 }
00949 }
00950 return rc;
00951 }
00952
00975 int NutTcpDeviceWrite(TCPSOCKET * sock, CONST void *buf, int size)
00976 {
00977 int rc;
00978 uint16_t sz;
00979
00980 uint8_t *buffer = (uint8_t*) buf;
00981
00982
00983
00984
00985 if (sock == 0)
00986 return -1;
00987 if (sock->so_state != TCPS_ESTABLISHED) {
00988 sock->so_last_error = ENOTCONN;
00989 return -1;
00990 }
00991
00992
00993 if (size == 0) {
00994 if (sock->so_devocnt) {
00995 if (SendBuffer(sock, sock->so_devobuf, sock->so_devocnt) < 0) {
00996 free(sock->so_devobuf);
00997 sock->so_devocnt = 0;
00998 return -1;
00999 }
01000 free(sock->so_devobuf);
01001 sock->so_devocnt = 0;
01002 }
01003 return 0;
01004 }
01005
01006
01007 if (sock->so_devocnt == 0) {
01008
01009
01010
01011
01012 if ((uint16_t) size >= sock->so_devobsz) {
01013 rc = size % sock->so_devobsz;
01014 if (SendBuffer(sock, buffer, size - rc) < 0)
01015 return -1;
01016 buffer += size - rc;
01017 } else
01018 rc = size;
01019
01020
01021
01022
01023 if (rc) {
01024 if (!(sock->so_devobuf = malloc(sock->so_devobsz)))
01025 return -1;
01026 memcpy(sock->so_devobuf, buffer, rc);
01027 sock->so_devocnt = rc;
01028 }
01029 return size;
01030 }
01031
01032
01033 if (sock->so_devocnt + size < sock->so_devobsz) {
01034 memcpy(sock->so_devobuf + sock->so_devocnt, buffer, size);
01035 sock->so_devocnt += size;
01036 return size;
01037 }
01038
01039
01040
01041
01042 sz = sock->so_devobsz - sock->so_devocnt;
01043 memcpy(sock->so_devobuf + sock->so_devocnt, buffer, sz);
01044 buffer += sz;
01045 if (SendBuffer(sock, sock->so_devobuf, sock->so_devobsz) < 0) {
01046 free(sock->so_devobuf);
01047 sock->so_devocnt = 0;
01048 return -1;
01049 }
01050
01051
01052
01053
01054
01055 sz = size - sz;
01056 if (sz >= sock->so_devobsz) {
01057 rc = size % sock->so_devobsz;
01058 if (SendBuffer(sock, buffer, sz - rc) < 0) {
01059 free(sock->so_devobuf);
01060 sock->so_devocnt = 0;
01061 return -1;
01062 }
01063 buffer += sz - rc;
01064 } else
01065 rc = sz;
01066
01067
01068
01069 if (rc)
01070 memcpy(sock->so_devobuf, buffer, rc);
01071 else
01072 free(sock->so_devobuf);
01073 sock->so_devocnt = rc;
01074
01075 return size;
01076 }
01077
01102 #ifdef __HARVARD_ARCH__
01103 int NutTcpDeviceWrite_P(TCPSOCKET * sock, PGM_P buffer, int size)
01104 {
01105 int rc;
01106 char *rp = 0;
01107
01108
01109
01110
01111
01112 if (size && (rp = NutHeapAlloc(size)) != 0)
01113 memcpy_P(rp, buffer, size);
01114 rc = NutTcpDeviceWrite(sock, rp, size);
01115 if (rp)
01116 NutHeapFree(rp);
01117
01118 return rc;
01119 }
01120 #endif
01121
01141 int NutTcpDeviceIOCtl(TCPSOCKET * sock, int cmd, void *param)
01142 {
01143 uint32_t *lvp = (uint32_t *) param;
01144 int rc = 0;
01145
01146 switch (cmd) {
01147 case IOCTL_GETFILESIZE:
01148 case IOCTL_GETINBUFCOUNT:
01149 *lvp = (sock->so_rx_cnt - sock->so_rd_cnt);
01150 break;
01151 case IOCTL_GETOUTBUFCOUNT:
01152 *lvp = (sock->so_devocnt);
01153 break;
01154 default:
01155 rc = -1;
01156 }
01157
01158 return rc;
01159 }
01160