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
00375 TCPSOCKET *NutTcpCreateSocket(void)
00376 {
00377 TCPSOCKET *sock = 0;
00378
00379 if (!registered) {
00380 if (NutRegisterIpHandler(IPPROTO_TCP, NutTcpInput) || NutTcpInitStateMachine()) {
00381 return NULL;
00382 }
00383 registered = 1;
00384 }
00385 if ((sock = calloc(1, sizeof(TCPSOCKET))) != 0) {
00386 sock->so_state = TCPS_CLOSED;
00387
00388
00389
00390
00391 sock->so_devtype = IFTYP_TCPSOCK;
00392 sock->so_devread = NutTcpDeviceRead;
00393 sock->so_devwrite = NutTcpDeviceWrite;
00394 #ifdef __HARVARD_ARCH__
00395 sock->so_devwrite_P = NutTcpDeviceWrite_P;
00396 #endif
00397 sock->so_devioctl = NutTcpDeviceIOCtl;
00398
00399 sock->so_tx_isn = NutGetTickCount();
00400 sock->so_tx_una = sock->so_tx_isn;
00401 sock->so_tx_nxt = sock->so_tx_isn;
00402 sock->so_rx_bsz = sock->so_rx_win = TCP_WINSIZE;
00403
00404 sock->so_mss = TCP_MSS;
00405 sock->so_rtto = 1000;
00406
00407 sock->so_next = tcpSocketList;
00408
00409 sock->so_devobsz = TCP_MSS;
00410
00411 tcpSocketList = sock;
00412 }
00413 return sock;
00414 }
00415
00435 int NutTcpSetSockOpt(TCPSOCKET * sock, int optname, CONST void *optval, int optlen)
00436 {
00437 int rc = -1;
00438
00439 if (sock == 0)
00440 return -1;
00441 switch (optname) {
00442
00443 case TCP_MAXSEG:
00444 if (optval == 0 || optlen != sizeof(uint16_t))
00445 sock->so_last_error = EINVAL;
00446 else if (sock->so_state != TCPS_CLOSED)
00447 sock->so_last_error = EISCONN;
00448 else {
00449 sock->so_mss = *((uint16_t *) optval);
00450 rc = 0;
00451 }
00452 break;
00453
00454 case SO_RCVBUF:
00455 if (optval == 0 || optlen != sizeof(uint16_t))
00456 sock->so_last_error = EINVAL;
00457 else {
00458 sock->so_rx_bsz = *((uint16_t *) optval);
00459 sock->so_rx_win = sock->so_rx_bsz;
00460 rc = 0;
00461 }
00462 break;
00463
00464 case SO_SNDTIMEO:
00465 if (optval == 0 || optlen != sizeof(uint32_t))
00466 sock->so_last_error = EINVAL;
00467 else {
00468 sock->so_write_to = *((uint32_t *) optval);
00469 rc = 0;
00470 }
00471 break;
00472
00473 case SO_RCVTIMEO:
00474 if (optval == 0 || optlen != sizeof(uint32_t))
00475 sock->so_last_error = EINVAL;
00476 else {
00477 sock->so_read_to = *((uint32_t *) optval);
00478 rc = 0;
00479 }
00480 break;
00481
00482 case SO_SNDBUF:
00483 if (optval == 0 || optlen != sizeof(uint16_t))
00484 sock->so_last_error = EINVAL;
00485 else {
00486 NutTcpDeviceWrite(sock, 0, 0);
00487 sock->so_devobsz = *((uint16_t *) optval);
00488 rc = 0;
00489 }
00490 break;
00491
00492 default:
00493 sock->so_last_error = ENOPROTOOPT;
00494 break;
00495 }
00496 return rc;
00497 }
00498
00518 int NutTcpGetSockOpt(TCPSOCKET * sock, int optname, void *optval, int optlen)
00519 {
00520 int rc = -1;
00521
00522 if (sock == 0)
00523 return -1;
00524 switch (optname) {
00525
00526 case TCP_MAXSEG:
00527 if (optval == 0 || optlen != sizeof(uint16_t))
00528 sock->so_last_error = EINVAL;
00529 else {
00530 *((uint16_t *) optval) = sock->so_mss;
00531 rc = 0;
00532 }
00533 break;
00534
00535 case SO_RCVBUF:
00536 if (optval == 0 || optlen != sizeof(uint16_t))
00537 sock->so_last_error = EINVAL;
00538 else {
00539 *((uint16_t *) optval) = sock->so_rx_bsz;
00540 rc = 0;
00541 }
00542 break;
00543
00544 case SO_SNDTIMEO:
00545 if (optval == 0 || optlen != sizeof(uint32_t))
00546 sock->so_last_error = EINVAL;
00547 else {
00548 *((uint32_t *) optval) = sock->so_write_to;
00549 rc = 0;
00550 }
00551 break;
00552
00553 case SO_RCVTIMEO:
00554 if (optval == 0 || optlen != sizeof(uint32_t))
00555 sock->so_last_error = EINVAL;
00556 else {
00557 *((uint32_t *) optval) = sock->so_read_to;
00558 rc = 0;
00559 }
00560 break;
00561
00562 case SO_SNDBUF:
00563 if (optval == 0 || optlen != sizeof(uint16_t))
00564 sock->so_last_error = EINVAL;
00565 else {
00566 *((uint16_t *) optval) = sock->so_devobsz;
00567 rc = 0;
00568 }
00569 break;
00570 default:
00571 sock->so_last_error = ENOPROTOOPT;
00572 break;
00573 }
00574 return rc;
00575 }
00576
00595 int NutTcpConnect(TCPSOCKET * sock, uint32_t addr, uint16_t port)
00596 {
00597 TCPSOCKET *sp;
00598 NUTDEVICE *dev;
00599
00600 if (sock == 0)
00601 return -1;
00602
00603
00604
00605
00606 if (sock->so_state == TCPS_LISTEN) {
00607 sock->so_last_error = EOPNOTSUPP;
00608 return -1;
00609 } else if (sock->so_state != TCPS_CLOSED) {
00610 sock->so_last_error = EISCONN;
00611 return -1;
00612 }
00613
00614
00615
00616
00617 do {
00618 if (++last_local_port == 0)
00619 last_local_port = 4096;
00620
00621 sp = tcpSocketList;
00622 while (sp) {
00623
00624 if (sp->so_local_port == htons(last_local_port))
00625 break;
00626 sp = sp->so_next;
00627 }
00628 } while (sp);
00629
00630
00631
00632
00633
00634 sock->so_local_port = htons(last_local_port);
00635 sock->so_remote_port = htons(port);
00636 sock->so_remote_addr = addr;
00637
00638
00639
00640
00641 if ((dev = NutIpRouteQuery(addr, 0)) != 0) {
00642 IFNET *nif = dev->dev_icb;
00643 sock->so_local_addr = nif->if_local_ip;
00644 } else {
00645 sock->so_last_error = EHOSTUNREACH;
00646 return -1;
00647 }
00648
00649
00650
00651
00652
00653 return NutTcpStateActiveOpenEvent(sock);
00654 }
00655
00671 int NutTcpAccept(TCPSOCKET * sock, uint16_t port)
00672 {
00673 sock->so_local_port = htons(port);
00674
00675 return NutTcpStatePassiveOpenEvent(sock);
00676 }
00677
00694 int NutTcpSend(TCPSOCKET * sock, CONST void *data, int len)
00695 {
00696 uint16_t unacked;
00697
00698
00699
00700
00701 NutThreadYield();
00702
00703 if (sock == 0)
00704 return -1;
00705 if (data == 0 || len == 0)
00706 return 0;
00707
00708
00709
00710
00711 if (len > sock->so_mss)
00712 len = sock->so_mss;
00713
00714 for (;;) {
00715
00716
00717
00718 if (sock->so_state != TCPS_ESTABLISHED) {
00719 sock->so_last_error = ENOTCONN;
00720 return -1;
00721 }
00722
00723
00724
00725
00726
00727
00728 unacked = sock->so_tx_nxt - sock->so_tx_una;
00729 if ((unacked >> 2) < sock->so_mss && len <= sock->so_tx_win - unacked) {
00730 break;
00731 }
00732 if (NutEventWait(&sock->so_tx_tq, sock->so_write_to)) {
00733 return 0;
00734 }
00735 }
00736
00737
00738
00739
00740
00741 sock->so_tx_flags |= SO_ACK;
00742 if (NutTcpOutput(sock, data, len))
00743 return -1;
00744 return len;
00745 }
00746
00764 int NutTcpReceive(TCPSOCKET * sock, void *data, int size)
00765 {
00766 int i;
00767
00768 NutThreadYield();
00769
00770
00771
00772 if (sock == 0)
00773 return -1;
00774 if (sock->so_state != TCPS_ESTABLISHED && sock->so_state != TCPS_CLOSE_WAIT) {
00775 sock->so_last_error = ENOTCONN;
00776 return -1;
00777 }
00778 if (data == 0 || size == 0)
00779 return 0;
00780
00781
00782
00783
00784
00785 while (sock->so_rx_cnt - sock->so_rd_cnt == 0) {
00786 if (sock->so_state != TCPS_ESTABLISHED) {
00787 sock->so_last_error = ENOTCONN;
00788 return -1;
00789 }
00790 if (NutEventWait(&sock->so_rx_tq, sock->so_read_to))
00791 return 0;
00792 }
00793
00794 if (size > sock->so_rx_cnt - sock->so_rd_cnt)
00795 size = sock->so_rx_cnt - sock->so_rd_cnt;
00796 if (size) {
00797 NETBUF *nb;
00798 uint16_t rd_cnt;
00799 uint16_t nb_cnt;
00800 uint16_t ab_cnt;
00801 uint16_t mv_cnt;
00802
00803 rd_cnt = sock->so_rd_cnt;
00804
00805 ab_cnt = 0;
00806 while (ab_cnt < size) {
00807 nb = sock->so_rx_buf;
00808 nb_cnt = nb->nb_ap.sz - rd_cnt;
00809 mv_cnt = size - ab_cnt;
00810 if (mv_cnt > nb_cnt)
00811 mv_cnt = nb_cnt;
00812 memcpy((char *) data + ab_cnt, (char *) (nb->nb_ap.vp) + rd_cnt, mv_cnt);
00813 ab_cnt += mv_cnt;
00814 rd_cnt += mv_cnt;
00815 if (mv_cnt >= nb_cnt) {
00816 sock->so_rx_buf = nb->nb_next;
00817 sock->so_rx_cnt -= rd_cnt;
00818 NutNetBufFree(nb);
00819 sock->so_rx_apc--;
00820 nb = sock->so_rx_buf;
00821 rd_cnt = 0;
00822 }
00823 }
00824 sock->so_rd_cnt = rd_cnt;
00825
00826
00827
00828
00829 if (sock->so_state == TCPS_ESTABLISHED) {
00830 i = sock->so_rx_win;
00831 if ((i += size) > sock->so_rx_bsz)
00832 i = sock->so_rx_bsz;
00833
00834 if (sock->so_rx_win <= sock->so_mss && i > sock->so_mss) {
00835 sock->so_rx_win = i;
00836 NutTcpStateWindowEvent(sock);
00837 } else {
00838 sock->so_rx_win = i;
00839 }
00840 }
00841 }
00842 return size;
00843 }
00844
00857 int NutTcpCloseSocket(TCPSOCKET * sock)
00858 {
00859
00860
00861 NutTcpDeviceWrite(sock, 0, 0);
00862 return NutTcpStateCloseEvent(sock);
00863 }
00864
00913 int NutTcpError(TCPSOCKET * sock)
00914 {
00915 if (sock == 0)
00916 return ENOTSOCK;
00917 return sock->so_last_error;
00918 }
00919
00939 int NutTcpDeviceRead(TCPSOCKET * sock, void *buffer, int size)
00940 {
00941 return NutTcpReceive(sock, buffer, size);
00942 }
00943
00944 static int SendBuffer(TCPSOCKET * sock, CONST void *buffer, int size)
00945 {
00946 int rc;
00947 int bite;
00948
00949 for (rc = 0; rc < size; rc += bite) {
00950 if ((bite = NutTcpSend(sock, (uint8_t *) buffer + rc, size - rc)) <= 0) {
00951 return -1;
00952 }
00953 }
00954 return rc;
00955 }
00956
00979 int NutTcpDeviceWrite(TCPSOCKET * sock, CONST void *buf, int size)
00980 {
00981 int rc;
00982 uint16_t sz;
00983
00984 uint8_t *buffer = (uint8_t*) buf;
00985
00986
00987
00988
00989 if (sock == 0)
00990 return -1;
00991 if (sock->so_state != TCPS_ESTABLISHED) {
00992 sock->so_last_error = ENOTCONN;
00993 return -1;
00994 }
00995
00996
00997 if (size == 0) {
00998 if (sock->so_devocnt) {
00999 if (SendBuffer(sock, sock->so_devobuf, sock->so_devocnt) < 0) {
01000 free(sock->so_devobuf);
01001 sock->so_devocnt = 0;
01002 return -1;
01003 }
01004 free(sock->so_devobuf);
01005 sock->so_devocnt = 0;
01006 }
01007 return 0;
01008 }
01009
01010
01011 if (sock->so_devocnt == 0) {
01012
01013
01014
01015
01016 if ((uint16_t) size >= sock->so_devobsz) {
01017 rc = size % sock->so_devobsz;
01018 if (SendBuffer(sock, buffer, size - rc) < 0)
01019 return -1;
01020 buffer += size - rc;
01021 } else
01022 rc = size;
01023
01024
01025
01026
01027 if (rc) {
01028 if (!(sock->so_devobuf = malloc(sock->so_devobsz)))
01029 return -1;
01030 memcpy(sock->so_devobuf, buffer, rc);
01031 sock->so_devocnt = rc;
01032 }
01033 return size;
01034 }
01035
01036
01037 if (sock->so_devocnt + size < sock->so_devobsz) {
01038 memcpy(sock->so_devobuf + sock->so_devocnt, buffer, size);
01039 sock->so_devocnt += size;
01040 return size;
01041 }
01042
01043
01044
01045
01046 sz = sock->so_devobsz - sock->so_devocnt;
01047 memcpy(sock->so_devobuf + sock->so_devocnt, buffer, sz);
01048 buffer += sz;
01049 if (SendBuffer(sock, sock->so_devobuf, sock->so_devobsz) < 0) {
01050 free(sock->so_devobuf);
01051 sock->so_devocnt = 0;
01052 return -1;
01053 }
01054
01055
01056
01057
01058
01059 sz = size - sz;
01060 if (sz >= sock->so_devobsz) {
01061 rc = size % sock->so_devobsz;
01062 if (SendBuffer(sock, buffer, sz - rc) < 0) {
01063 free(sock->so_devobuf);
01064 sock->so_devocnt = 0;
01065 return -1;
01066 }
01067 buffer += sz - rc;
01068 } else
01069 rc = sz;
01070
01071
01072
01073 if (rc)
01074 memcpy(sock->so_devobuf, buffer, rc);
01075 else
01076 free(sock->so_devobuf);
01077 sock->so_devocnt = rc;
01078
01079 return size;
01080 }
01081
01106 #ifdef __HARVARD_ARCH__
01107 int NutTcpDeviceWrite_P(TCPSOCKET * sock, PGM_P buffer, int size)
01108 {
01109 int rc;
01110 char *rp = 0;
01111
01112
01113
01114
01115
01116 if (size && (rp = NutHeapAlloc(size)) != 0)
01117 memcpy_P(rp, buffer, size);
01118 rc = NutTcpDeviceWrite(sock, rp, size);
01119 if (rp)
01120 NutHeapFree(rp);
01121
01122 return rc;
01123 }
01124 #endif
01125
01145 int NutTcpDeviceIOCtl(TCPSOCKET * sock, int cmd, void *param)
01146 {
01147 uint32_t *lvp = (uint32_t *) param;
01148 int rc = 0;
01149
01150 switch (cmd) {
01151 case IOCTL_GETFILESIZE:
01152 case IOCTL_GETINBUFCOUNT:
01153 *lvp = (sock->so_rx_cnt - sock->so_rd_cnt);
01154 break;
01155 case IOCTL_GETOUTBUFCOUNT:
01156 *lvp = (sock->so_devocnt);
01157 break;
01158 default:
01159 rc = -1;
01160 }
01161
01162 return rc;
01163 }
01164