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 nb = sock->so_rx_buf;
00820 rd_cnt = 0;
00821 }
00822 }
00823 sock->so_rd_cnt = rd_cnt;
00824
00825
00826
00827
00828 if (sock->so_state == TCPS_ESTABLISHED) {
00829 i = sock->so_rx_win;
00830 if ((i += size) > sock->so_rx_bsz)
00831 i = sock->so_rx_bsz;
00832
00833 if (sock->so_rx_win <= sock->so_mss && i > sock->so_mss) {
00834 sock->so_rx_win = i;
00835 NutTcpStateWindowEvent(sock);
00836 } else {
00837 sock->so_rx_win = i;
00838 }
00839 }
00840 }
00841 return size;
00842 }
00843
00856 int NutTcpCloseSocket(TCPSOCKET * sock)
00857 {
00858
00859
00860 NutTcpDeviceWrite(sock, 0, 0);
00861 return NutTcpStateCloseEvent(sock);
00862 }
00863
00912 int NutTcpError(TCPSOCKET * sock)
00913 {
00914 if (sock == 0)
00915 return ENOTSOCK;
00916 return sock->so_last_error;
00917 }
00918
00938 int NutTcpDeviceRead(TCPSOCKET * sock, void *buffer, int size)
00939 {
00940 return NutTcpReceive(sock, buffer, size);
00941 }
00942
00943 static int SendBuffer(TCPSOCKET * sock, CONST void *buffer, int size)
00944 {
00945 int rc;
00946 int bite;
00947
00948 for (rc = 0; rc < size; rc += bite) {
00949 if ((bite = NutTcpSend(sock, (uint8_t *) buffer + rc, size - rc)) <= 0) {
00950 return -1;
00951 }
00952 }
00953 return rc;
00954 }
00955
00978 int NutTcpDeviceWrite(TCPSOCKET * sock, CONST void *buf, int size)
00979 {
00980 int rc;
00981 uint16_t sz;
00982
00983 uint8_t *buffer = (uint8_t*) buf;
00984
00985
00986
00987
00988 if (sock == 0)
00989 return -1;
00990 if (sock->so_state != TCPS_ESTABLISHED) {
00991 sock->so_last_error = ENOTCONN;
00992 return -1;
00993 }
00994
00995
00996 if (size == 0) {
00997 if (sock->so_devocnt) {
00998 if (SendBuffer(sock, sock->so_devobuf, sock->so_devocnt) < 0) {
00999 free(sock->so_devobuf);
01000 sock->so_devocnt = 0;
01001 return -1;
01002 }
01003 free(sock->so_devobuf);
01004 sock->so_devocnt = 0;
01005 }
01006 return 0;
01007 }
01008
01009
01010 if (sock->so_devocnt == 0) {
01011
01012
01013
01014
01015 if ((uint16_t) size >= sock->so_devobsz) {
01016 rc = size % sock->so_devobsz;
01017 if (SendBuffer(sock, buffer, size - rc) < 0)
01018 return -1;
01019 buffer += size - rc;
01020 } else
01021 rc = size;
01022
01023
01024
01025
01026 if (rc) {
01027 if (!(sock->so_devobuf = malloc(sock->so_devobsz)))
01028 return -1;
01029 memcpy(sock->so_devobuf, buffer, rc);
01030 sock->so_devocnt = rc;
01031 }
01032 return size;
01033 }
01034
01035
01036 if (sock->so_devocnt + size < sock->so_devobsz) {
01037 memcpy(sock->so_devobuf + sock->so_devocnt, buffer, size);
01038 sock->so_devocnt += size;
01039 return size;
01040 }
01041
01042
01043
01044
01045 sz = sock->so_devobsz - sock->so_devocnt;
01046 memcpy(sock->so_devobuf + sock->so_devocnt, buffer, sz);
01047 buffer += sz;
01048 if (SendBuffer(sock, sock->so_devobuf, sock->so_devobsz) < 0) {
01049 free(sock->so_devobuf);
01050 sock->so_devocnt = 0;
01051 return -1;
01052 }
01053
01054
01055
01056
01057
01058 sz = size - sz;
01059 if (sz >= sock->so_devobsz) {
01060 rc = size % sock->so_devobsz;
01061 if (SendBuffer(sock, buffer, sz - rc) < 0) {
01062 free(sock->so_devobuf);
01063 sock->so_devocnt = 0;
01064 return -1;
01065 }
01066 buffer += sz - rc;
01067 } else
01068 rc = sz;
01069
01070
01071
01072 if (rc)
01073 memcpy(sock->so_devobuf, buffer, rc);
01074 else
01075 free(sock->so_devobuf);
01076 sock->so_devocnt = rc;
01077
01078 return size;
01079 }
01080
01105 #ifdef __HARVARD_ARCH__
01106 int NutTcpDeviceWrite_P(TCPSOCKET * sock, PGM_P buffer, int size)
01107 {
01108 int rc;
01109 char *rp = 0;
01110
01111
01112
01113
01114
01115 if (size && (rp = NutHeapAlloc(size)) != 0)
01116 memcpy_P(rp, buffer, size);
01117 rc = NutTcpDeviceWrite(sock, rp, size);
01118 if (rp)
01119 NutHeapFree(rp);
01120
01121 return rc;
01122 }
01123 #endif
01124
01144 int NutTcpDeviceIOCtl(TCPSOCKET * sock, int cmd, void *param)
01145 {
01146 uint32_t *lvp = (uint32_t *) param;
01147 int rc = 0;
01148
01149 switch (cmd) {
01150 case IOCTL_GETFILESIZE:
01151 case IOCTL_GETINBUFCOUNT:
01152 *lvp = (sock->so_rx_cnt - sock->so_rd_cnt);
01153 break;
01154 case IOCTL_GETOUTBUFCOUNT:
01155 *lvp = (sock->so_devocnt);
01156 break;
01157 default:
01158 rc = -1;
01159 }
01160
01161 return rc;
01162 }
01163