diff --git a/stio/lib/main.c b/stio/lib/main.c index 227074a..4c89a88 100644 --- a/stio/lib/main.c +++ b/stio/lib/main.c @@ -40,6 +40,8 @@ #include #include +#include + #if defined(HAVE_OPENSSL_SSL_H) && defined(HAVE_SSL) # include # if defined(HAVE_OPENSSL_ERR_H) @@ -126,11 +128,11 @@ static void tcp_sck_on_disconnect (stio_dev_sck_t* tcp) switch (STIO_DEV_SCK_GET_PROGRESS(tcp)) { case STIO_DEV_SCK_CONNECTING: - printf ("OUTGOING TCP DISCONNECTED - FAILED TO CONNECT (%d) TO REMOTE SERVER\n", (int)tcp->sck); + printf ("OUTGOING SESSION DISCONNECTED - FAILED TO CONNECT (%d) TO REMOTE SERVER\n", (int)tcp->sck); break; case STIO_DEV_SCK_CONNECTING_SSL: - printf ("OUTGOING TCP DISCONNECTED - FAILED TO SSL-CONNECT (%d) TO REMOTE SERVER\n", (int)tcp->sck); + printf ("OUTGOING SESSION DISCONNECTED - FAILED TO SSL-CONNECT (%d) TO REMOTE SERVER\n", (int)tcp->sck); break; case STIO_DEV_SCK_LISTENING: @@ -150,7 +152,7 @@ static void tcp_sck_on_disconnect (stio_dev_sck_t* tcp) break; default: - printf ("TCP DISCONNECTED - THIS MUST NOT HAPPEN (%d - %x)\n", (int)tcp->sck, (unsigned int)tcp->state); + printf ("SOCKET DEVICE DISCONNECTED (%d - %x)\n", (int)tcp->sck, (unsigned int)tcp->state); break; } } @@ -203,6 +205,8 @@ else printf ("ENABLING READING..............................\n"); stio_dev_sck_read (tcp, 1); + + //stio_dev_sck_timedread (tcp, 1, 1000); } return 0; } @@ -237,12 +241,14 @@ free (xxx); if (n <= -1) return -1; } + +printf ("DISABLING READING..............................\n"); + stio_dev_sck_read (tcp, 0); + /* post the write finisher */ n = stio_dev_sck_write (tcp, STIO_NULL, 0, STIO_NULL, STIO_NULL); if (n <= -1) return -1; -printf ("DISABLING READING..............................\n"); - stio_dev_sck_read (tcp, 0); return 0; /* return 1; let the main loop to read more greedily without consulting the multiplexer */ @@ -250,6 +256,26 @@ printf ("DISABLING READING..............................\n"); /* ========================================================================= */ +static void pro_on_close (stio_dev_pro_t* dev, stio_dev_pro_sid_t sid) +{ +printf (">>>>>>>>>>>>> ON CLOSE OF SLAVE %d.\n", sid); +} + +static int pro_on_read (stio_dev_pro_t* dev, const void* data, stio_iolen_t dlen, stio_dev_pro_sid_t sid) +{ +printf ("PROCESS READ DATA on SLAVE[%d]... [%.*s]\n", (int)sid, (int)dlen, (char*)data); + return 0; +} + + +static int pro_on_write (stio_dev_pro_t* dev, stio_iolen_t wrlen, void* wrctx) +{ +printf ("PROCESS WROTE DATA...\n"); + return 0; +} + +/* ========================================================================= */ + static int arp_sck_on_read (stio_dev_sck_t* dev, const void* data, stio_iolen_t dlen, const stio_sckaddr_t* srcaddr) { stio_etharp_pkt_t* eap; @@ -272,26 +298,232 @@ static int arp_sck_on_write (stio_dev_sck_t* dev, stio_iolen_t wrlen, void* wrct return 0; } +static void arp_sck_on_disconnect (stio_dev_sck_t* dev) +{ +printf ("SHUTTING DOWN ARP SOCKET %d...\n", dev->sck); +} + +static int setup_arp_tester (stio_t* stio) +{ + stio_sckaddr_t ethdst; + stio_etharp_pkt_t etharp; + stio_dev_sck_make_t sck_make; + stio_dev_sck_t* sck; + + memset (&sck_make, 0, STIO_SIZEOF(sck_make)); + sck_make.type = STIO_DEV_SCK_ARP; + //sck_make.type = STIO_DEV_SCK_ARP_DGRAM; + sck_make.on_write = arp_sck_on_write; + sck_make.on_read = arp_sck_on_read; + sck_make.on_disconnect = arp_sck_on_disconnect; + sck = stio_dev_sck_make (stio, 0, &sck_make); + if (!sck) + { + printf ("Cannot make socket device\n"); + return -1; + } + + //stio_sckaddr_initforeth (ðdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xFF\xFF\xFF\xFF\xFF\xFF"); + stio_sckaddr_initforeth (ðdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF"); + + memset (ðarp, 0, sizeof(etharp)); + + memcpy (etharp.ethhdr.source, "\xB8\x6B\x23\x9C\x10\x76", STIO_ETHADDR_LEN); + //memcpy (etharp.ethhdr.dest, "\xFF\xFF\xFF\xFF\xFF\xFF", STIO_ETHADDR_LEN); + memcpy (etharp.ethhdr.dest, "\xAA\xBB\xFF\xCC\xDD\xFF", STIO_ETHADDR_LEN); + etharp.ethhdr.proto = STIO_CONST_HTON16(STIO_ETHHDR_PROTO_ARP); + + etharp.arphdr.htype = STIO_CONST_HTON16(STIO_ARPHDR_HTYPE_ETH); + etharp.arphdr.ptype = STIO_CONST_HTON16(STIO_ARPHDR_PTYPE_IP4); + etharp.arphdr.hlen = STIO_ETHADDR_LEN; + etharp.arphdr.plen = STIO_IP4ADDR_LEN; + etharp.arphdr.opcode = STIO_CONST_HTON16(STIO_ARPHDR_OPCODE_REQUEST); + + memcpy (etharp.arppld.sha, "\xB8\x6B\x23\x9C\x10\x76", STIO_ETHADDR_LEN); + + if (stio_dev_sck_write (sck, ðarp, sizeof(etharp), NULL, ðdst) <= -1) + //if (stio_dev_sck_write (sck, ðarp.arphdr, sizeof(etharp) - sizeof(etharp.ethhdr), NULL, ðaddr) <= -1) + { + printf ("CANNOT WRITE ARP...\n"); + } + + + return 0; +} + /* ========================================================================= */ -static void pro_on_close (stio_dev_pro_t* dev, stio_dev_pro_sid_t sid) +struct icmpxtn_t { -printf (">>>>>>>>>>>>> ON CLOSE OF SLAVE %d.\n", sid); + stio_uint16_t icmp_seq; + stio_tmridx_t tmout_jobidx; + int reply_received; +}; + +typedef struct icmpxtn_t icmpxtn_t; + +static int schedule_icmp_wait (stio_dev_sck_t* dev); + +static void send_icmp (stio_dev_sck_t* dev, stio_uint16_t seq) +{ + stio_sckaddr_t dstaddr; + stio_ip4addr_t ia; + stio_icmphdr_t* icmphdr; + stio_uint8_t buf[512]; + + inet_pton (AF_INET, "192.168.1.131", &ia); + stio_sckaddr_initforip4 (&dstaddr, 0, &ia); + + memset(buf, 0, STIO_SIZEOF(buf)); + icmphdr = (stio_icmphdr_t*)buf; + icmphdr->type = STIO_ICMP_ECHO_REQUEST; + icmphdr->u.echo.id = STIO_CONST_HTON16(100); + icmphdr->u.echo.seq = stio_hton16(seq); + + memset (&buf[STIO_SIZEOF(*icmphdr)], 'A', STIO_SIZEOF(buf) - STIO_SIZEOF(*icmphdr)); + icmphdr->checksum = stio_checksumip (icmphdr, STIO_SIZEOF(buf)); + + if (stio_dev_sck_write (dev, buf, STIO_SIZEOF(buf), NULL, &dstaddr) <= -1) + { + printf ("CANNOT WRITE ICMP...\n"); + stio_dev_sck_halt (dev); + } + + if (schedule_icmp_wait (dev) <= -1) + { + printf ("CANNOT SCHEDULE ICMP WAIT...\n"); + stio_dev_sck_halt (dev); + } } -static int pro_on_read (stio_dev_pro_t* dev, const void* data, stio_iolen_t dlen, stio_dev_pro_sid_t sid) +static void on_icmp_due (stio_t* stio, const stio_ntime_t* now, stio_tmrjob_t* tmrjob) { -printf ("PROCESS READ DATA on SLAVE[%d]... [%.*s]\n", (int)sid, (int)dlen, (char*)data); + stio_dev_sck_t* dev; + icmpxtn_t* icmpxtn; + + dev = tmrjob->ctx; + icmpxtn = (icmpxtn_t*)(dev + 1); + + if (icmpxtn->reply_received) + icmpxtn->reply_received = 0; + else + printf ("NO ICMP REPLY RECEIVED....\n"); + + send_icmp (dev, ++icmpxtn->icmp_seq); +} + +static int schedule_icmp_wait (stio_dev_sck_t* dev) +{ + icmpxtn_t* icmpxtn; + stio_tmrjob_t tmrjob; + stio_ntime_t fire_after; + + icmpxtn = (icmpxtn_t*)(dev + 1); + stio_inittime (&fire_after, 2, 0); + + memset (&tmrjob, 0, STIO_SIZEOF(tmrjob)); + tmrjob.ctx = dev; + stio_gettime (&tmrjob.when); + stio_addtime (&tmrjob.when, &fire_after, &tmrjob.when); + tmrjob.handler = on_icmp_due; + tmrjob.idxptr = &icmpxtn->tmout_jobidx; + + assert (icmpxtn->tmout_jobidx == STIO_TMRIDX_INVALID); + + return (stio_instmrjob (dev->stio, &tmrjob) == STIO_TMRIDX_INVALID)? -1: 0; +} + +static int icmp_sck_on_read (stio_dev_sck_t* dev, const void* data, stio_iolen_t dlen, const stio_sckaddr_t* srcaddr) +{ + icmpxtn_t* icmpxtn; + stio_iphdr_t* iphdr; + stio_icmphdr_t* icmphdr; + + /* when received, the data contains the IP header.. */ + icmpxtn = (icmpxtn_t*)(dev + 1); + + if (dlen < STIO_SIZEOF(*iphdr) + STIO_SIZEOF(*icmphdr)) + { + printf ("INVALID ICMP PACKET.. TOO SHORT...%d\n", (int)dlen); + } + else + { + /* TODO: consider IP options... */ + iphdr = (stio_iphdr_t*)data; + icmphdr = (stio_icmphdr_t*)((stio_uint8_t*)data + (iphdr->ihl * 4)); + + /* TODO": check srcaddr against target */ + + if (icmphdr->type == STIO_ICMP_ECHO_REPLY && + stio_ntoh16(icmphdr->u.echo.seq) == icmpxtn->icmp_seq) /* TODO: more check.. echo.id.. */ + { + icmpxtn->reply_received = 1; + printf ("ICMP REPLY RECEIVED...ID %d SEQ %d\n", (int)stio_ntoh16(icmphdr->u.echo.id), (int)stio_ntoh16(icmphdr->u.echo.seq)); + } + else + { + printf ("GARBAGE ICMP PACKET...LEN %d SEQ %d,%d\n", (int)dlen, (int)icmpxtn->icmp_seq, (int)stio_ntoh16(icmphdr->u.echo.seq)); + } + } return 0; } -static int pro_on_write (stio_dev_pro_t* dev, stio_iolen_t wrlen, void* wrctx) +static int icmp_sck_on_write (stio_dev_sck_t* dev, stio_iolen_t wrlen, void* wrctx, const stio_sckaddr_t* dstaddr) { -printf ("PROCESS WROTE DATA...\n"); + /*icmpxtn_t* icmpxtn; + + icmpxtn = (icmpxtn_t*)(dev + 1); */ + return 0; } +static void icmp_sck_on_disconnect (stio_dev_sck_t* dev) +{ + icmpxtn_t* icmpxtn; + + icmpxtn = (icmpxtn_t*)(dev + 1); + +printf ("SHUTTING DOWN ICMP SOCKET %d...\n", dev->sck); + if (icmpxtn->tmout_jobidx != STIO_TMRIDX_INVALID) + { + + stio_deltmrjob (dev->stio, icmpxtn->tmout_jobidx); + icmpxtn->tmout_jobidx = STIO_TMRIDX_INVALID; + } +} + +static int setup_ping4_tester (stio_t* stio) +{ + stio_dev_sck_make_t sck_make; + stio_dev_sck_t* sck; + icmpxtn_t* icmpxtn; + + memset (&sck_make, 0, STIO_SIZEOF(sck_make)); + sck_make.type = STIO_DEV_SCK_ICMP4; + sck_make.on_write = icmp_sck_on_write; + sck_make.on_read = icmp_sck_on_read; + sck_make.on_disconnect = icmp_sck_on_disconnect; + + sck = stio_dev_sck_make (stio, STIO_SIZEOF(icmpxtn_t), &sck_make); + if (!sck) + { + printf ("Cannot make ICMP4 socket device\n"); + return -1; + } + + icmpxtn = (icmpxtn_t*)(sck + 1); + icmpxtn->tmout_jobidx = STIO_TMRIDX_INVALID; + icmpxtn->icmp_seq = 0; + + /*TODO: stio_dev_sck_setbroadcast (sck, 1);*/ + + send_icmp (sck, ++icmpxtn->icmp_seq); + + return 0; +} + + /* ========================================================================= */ static stio_t* g_stio; @@ -306,7 +538,6 @@ int main () int i; stio_t* stio; - stio_dev_sck_t* sck; stio_dev_sck_t* tcp[3]; struct sigaction sigact; @@ -314,8 +545,7 @@ int main () stio_dev_sck_listen_t tcp_lstn; stio_dev_sck_bind_t tcp_bind; stio_dev_sck_make_t tcp_make; - - stio_dev_sck_make_t sck_make; + tcp_server_t* ts; #if defined(USE_SSL) @@ -363,6 +593,7 @@ int main () tcp_make.type = STIO_DEV_SCK_TCP4; tcp_make.on_write = tcp_sck_on_write; tcp_make.on_read = tcp_sck_on_read; + tcp_make.on_disconnect = tcp_sck_on_disconnect; tcp[0] = stio_dev_sck_make (stio, STIO_SIZEOF(tcp_server_t), &tcp_make); if (!tcp[0]) { @@ -382,7 +613,6 @@ int main () stio_inittime (&tcp_conn.connect_tmout, 5, 0); tcp_conn.on_connect = tcp_sck_on_connect; - tcp_conn.on_disconnect = tcp_sck_on_disconnect; tcp_conn.options = STIO_DEV_SCK_CONNECT_SSL; if (stio_dev_sck_connect (tcp[0], &tcp_conn) <= -1) { @@ -395,7 +625,7 @@ int main () tcp_make.type = STIO_DEV_SCK_TCP4; tcp_make.on_write = tcp_sck_on_write; tcp_make.on_read = tcp_sck_on_read; - + tcp_make.on_disconnect = tcp_sck_on_disconnect; tcp[1] = stio_dev_sck_make (stio, STIO_SIZEOF(tcp_server_t), &tcp_make); if (!tcp[1]) @@ -419,7 +649,6 @@ int main () tcp_lstn.backlogs = 100; tcp_lstn.on_connect = tcp_sck_on_connect; - tcp_lstn.on_disconnect = tcp_sck_on_disconnect; if (stio_dev_sck_listen (tcp[1], &tcp_lstn) <= -1) { printf ("stio_dev_sck_listen() failed....\n"); @@ -431,6 +660,7 @@ int main () tcp_make.type = STIO_DEV_SCK_TCP4; tcp_make.on_write = tcp_sck_on_write; tcp_make.on_read = tcp_sck_on_read; + tcp_make.on_disconnect = tcp_sck_on_disconnect; tcp[2] = stio_dev_sck_make (stio, STIO_SIZEOF(tcp_server_t), &tcp_make); if (!tcp[2]) @@ -456,7 +686,6 @@ int main () tcp_lstn.backlogs = 100; tcp_lstn.on_connect = tcp_sck_on_connect; - tcp_lstn.on_disconnect = tcp_sck_on_disconnect; if (stio_dev_sck_listen (tcp[2], &tcp_lstn) <= -1) { printf ("stio_dev_sck_listen() failed....\n"); @@ -464,49 +693,9 @@ int main () } //stio_dev_sck_sendfile (tcp[2], fd, offset, count); -#if 1 -{ - stio_sckaddr_t ethdst; - stio_etharp_pkt_t etharp; - - memset (&sck_make, 0, STIO_SIZEOF(sck_make)); - sck_make.type = STIO_DEV_SCK_ARP; - //sck_make.type = STIO_DEV_SCK_ARP_DGRAM; - sck_make.on_write = arp_sck_on_write; - sck_make.on_read = arp_sck_on_read; - sck = stio_dev_sck_make (stio, 0, &sck_make); - if (!sck) - { - printf ("Cannot make socket device\n"); - goto oops; - } - - //stio_sckaddr_initforeth (ðdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xFF\xFF\xFF\xFF\xFF\xFF"); - stio_sckaddr_initforeth (ðdst, if_nametoindex("enp0s25.3"), (stio_ethaddr_t*)"\xAA\xBB\xFF\xCC\xDD\xFF"); - - memset (ðarp, 0, sizeof(etharp)); - - memcpy (etharp.ethhdr.source, "\xB8\x6B\x23\x9C\x10\x76", STIO_ETHADDR_LEN); - //memcpy (etharp.ethhdr.dest, "\xFF\xFF\xFF\xFF\xFF\xFF", STIO_ETHADDR_LEN); - memcpy (etharp.ethhdr.dest, "\xAA\xBB\xFF\xCC\xDD\xFF", STIO_ETHADDR_LEN); - etharp.ethhdr.proto = STIO_CONST_HTON16(STIO_ETHHDR_PROTO_ARP); - - etharp.arphdr.htype = STIO_CONST_HTON16(STIO_ARPHDR_HTYPE_ETH); - etharp.arphdr.ptype = STIO_CONST_HTON16(STIO_ARPHDR_PTYPE_IP4); - etharp.arphdr.hlen = STIO_ETHADDR_LEN; - etharp.arphdr.plen = STIO_IP4ADDR_LEN; - etharp.arphdr.opcode = STIO_CONST_HTON16(STIO_ARPHDR_OPCODE_REQUEST); - - memcpy (etharp.arppld.sha, "\xB8\x6B\x23\x9C\x10\x76", STIO_ETHADDR_LEN); - - if (stio_dev_sck_write (sck, ðarp, sizeof(etharp), NULL, ðdst) <= -1) - //if (stio_dev_sck_write (sck, ðarp.arphdr, sizeof(etharp) - sizeof(etharp.ethhdr), NULL, ðaddr) <= -1) - { - printf ("CANNOT WRITE ARP...\n"); - } -} -#endif + if (setup_arp_tester(stio) <= -1) goto oops; + if (setup_ping4_tester(stio) <= -1) goto oops; for (i = 0; i < 5; i++) diff --git a/stio/lib/stio-prv.h b/stio/lib/stio-prv.h index 66557e4..82f9c7e 100644 --- a/stio/lib/stio-prv.h +++ b/stio/lib/stio-prv.h @@ -40,17 +40,6 @@ #define STIO_MEMCMP(dst,src,count) memcmp(dst,src,count) #define STIO_ASSERT assert - -struct stio_tmrjob_t -{ - void* ctx; - stio_ntime_t when; - stio_tmrjob_handler_t handler; - stio_tmridx_t* idxptr; /* pointer to the index holder */ -}; - -#define STIO_TMRIDX_INVALID ((stio_tmridx_t)-1) - typedef struct stio_mux_t stio_mux_t; struct stio_t diff --git a/stio/lib/stio-sck.c b/stio/lib/stio-sck.c index c65f1c3..d4ea564 100644 --- a/stio/lib/stio-sck.c +++ b/stio/lib/stio-sck.c @@ -116,7 +116,6 @@ stio_sckhnd_t stio_openasyncsck (stio_t* stio, int domain, int type, int proto) return STIO_SCKHND_INVALID; } - #endif return sck; @@ -249,15 +248,29 @@ struct sck_type_map_t static struct sck_type_map_t sck_type_map[] = { + /* STIO_DEV_SCK_TCP4 */ { AF_INET, SOCK_STREAM, 0, STIO_DEV_CAPA_STREAM | STIO_DEV_CAPA_OUT_QUEUED }, + + /* STIO_DEV_SCK_TCP6 */ { AF_INET6, SOCK_STREAM, 0, STIO_DEV_CAPA_STREAM | STIO_DEV_CAPA_OUT_QUEUED }, + + /* STIO_DEV_SCK_UPD4 */ { AF_INET, SOCK_DGRAM, 0, 0 }, + + /* STIO_DEV_SCK_UDP6 */ { AF_INET6, SOCK_DGRAM, 0, 0 }, - { AF_PACKET, SOCK_RAW, STIO_CONST_HTON16(0x0806), 0 }, - { AF_PACKET, SOCK_DGRAM, STIO_CONST_HTON16(0x0806), 0 }, + /* STIO_DEV_SCK_ARP - Ethernet type is 2 bytes long. Protocol must be specified in the network byte order */ + { AF_PACKET, SOCK_RAW, STIO_CONST_HTON16(STIO_ETHHDR_PROTO_ARP), 0 }, - { AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, } + /* STIO_DEV_SCK_DGRAM */ + { AF_PACKET, SOCK_DGRAM, STIO_CONST_HTON16(STIO_ETHHDR_PROTO_ARP), 0 }, + + /* STIO_DEV_SCK_ICMP4 - IP protocol field is 1 byte only. no byte order conversion is needed */ + { AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, }, + + /* STIO_DEV_SCK_ICMP6 - IP protocol field is 1 byte only. no byte order conversion is needed */ + { AF_INET6, SOCK_RAW, IPPROTO_ICMP, 0, } }; /* ======================================================================== */ @@ -346,6 +359,7 @@ static int dev_sck_make (stio_dev_t* dev, void* ctx) rdev->dev_capa = STIO_DEV_CAPA_IN | STIO_DEV_CAPA_OUT | sck_type_map[arg->type].extra_dev_capa; rdev->on_write = arg->on_write; rdev->on_read = arg->on_read; + rdev->on_disconnect = arg->on_disconnect; rdev->type = arg->type; rdev->tmrjob_index = STIO_TMRIDX_INVALID; @@ -365,7 +379,7 @@ static int dev_sck_make_client (stio_dev_t* dev, void* ctx) stio_dev_sck_t* rdev = (stio_dev_sck_t*)dev; stio_syshnd_t* sck = (stio_syshnd_t*)ctx; - /* nothing special is done here except setting the socket handle. + /* nothing special is done here except setting the sock et handle. * most of the initialization is done by the listening socket device * after a client socket has been created. */ @@ -393,12 +407,12 @@ static int dev_sck_kill (stio_dev_t* dev, int force) if (IS_STATEFUL(rdev)) { - if (STIO_DEV_SCK_GET_PROGRESS(rdev)) - { + /*if (STIO_DEV_SCK_GET_PROGRESS(rdev)) + {*/ /* for STIO_DEV_SCK_CONNECTING, STIO_DEV_SCK_CONNECTING_SSL, and STIO_DEV_ACCEPTING_SSL * on_disconnect() is called without corresponding on_connect() */ if (rdev->on_disconnect) rdev->on_disconnect (rdev); - } + /*}*/ if (rdev->tmrjob_index != STIO_TMRIDX_INVALID) { @@ -410,6 +424,8 @@ static int dev_sck_kill (stio_dev_t* dev, int force) { STIO_ASSERT (rdev->state == 0); STIO_ASSERT (rdev->tmrjob_index == STIO_TMRIDX_INVALID); + + if (rdev->on_disconnect) rdev->on_disconnect (rdev); } #if defined(USE_SSL) @@ -533,8 +549,6 @@ static int dev_sck_write_stateful (stio_dev_t* dev, const void* data, stio_iolen { int err = SSL_get_error ((SSL*)rdev->ssl, x); if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) return 0; - /*else if (err == SSL_ERROR_SYSCALL) - rdev->stio->errnum = stio_syserrtoerrnum(errno); */ rdev->stio->errnum = STIO_ESYSERR; return -1; } @@ -932,7 +946,6 @@ fcntl (rdev->sck, F_SETFL, flags | O_NONBLOCK); rdev->remoteaddr = conn->remoteaddr; rdev->on_connect = conn->on_connect; - rdev->on_disconnect = conn->on_disconnect; #if defined(USE_SSL) rdev->ssl_ctx = ssl_ctx; #endif @@ -960,7 +973,6 @@ fcntl (rdev->sck, F_SETFL, flags | O_NONBLOCK); /* connected immediately */ rdev->remoteaddr = conn->remoteaddr; rdev->on_connect = conn->on_connect; - rdev->on_disconnect = conn->on_disconnect; sl = STIO_SIZEOF(localaddr); if (getsockname (rdev->sck, (struct sockaddr*)&localaddr, &sl) == 0) rdev->localaddr = localaddr; @@ -1055,7 +1067,6 @@ fcntl (rdev->sck, F_SETFL, flags | O_NONBLOCK); STIO_DEV_SCK_SET_PROGRESS (rdev, STIO_DEV_SCK_LISTENING); rdev->on_connect = lstn->on_connect; - rdev->on_disconnect = lstn->on_disconnect; return 0; } } @@ -1598,3 +1609,29 @@ int stio_dev_sck_timedwrite (stio_dev_sck_t* dev, const void* data, stio_iolen_t stio_devaddr_t devaddr; return stio_dev_timedwrite ((stio_dev_t*)dev, data, dlen, tmout, wrctx, sckaddr_to_devaddr(dev, dstaddr, &devaddr)); } + + + + + + +/* ========================================================================= */ + +stio_uint16_t stio_checksumip (const void* hdr, stio_size_t len) +{ + stio_uint32_t sum = 0; + stio_uint16_t *ptr = (stio_uint16_t*)hdr; + + + while (len > 1) + { + sum += *ptr++; + if (sum & 0x80000000) + sum = (sum & 0xFFFF) + (sum >> 16); + len -= 2; + } + + while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); + + return (stio_uint16_t)~sum; +} diff --git a/stio/lib/stio-sck.h b/stio/lib/stio-sck.h index 0ae4554..6b4fe91 100644 --- a/stio/lib/stio-sck.h +++ b/stio/lib/stio-sck.h @@ -29,6 +29,188 @@ #include +/* ========================================================================= */ +/* TOOD: move these to a separte file */ + +#define STIO_ETHHDR_PROTO_IP4 0x0800 +#define STIO_ETHHDR_PROTO_ARP 0x0806 +#define STIO_ETHHDR_PROTO_8021Q 0x8100 /* 802.1Q VLAN */ +#define STIO_ETHHDR_PROTO_IP6 0x86DD + + +#define STIO_ARPHDR_OPCODE_REQUEST 1 +#define STIO_ARPHDR_OPCODE_REPLY 2 + +#define STIO_ARPHDR_HTYPE_ETH 0x0001 +#define STIO_ARPHDR_PTYPE_IP4 0x0800 + +#define STIO_ETHADDR_LEN 6 +#define STIO_IP4ADDR_LEN 4 +#define STIO_IP6ADDR_LEN 16 + + +#if defined(__GNUC__) +# define STIO_PACKED __attribute__((__packed__)) + +#else +# define STIO_PACKED +# STIO_PACK_PUSH pack(push) +# STIO_PACK_PUSH pack(push) +# STIO_PACK(x) pack(x) +#endif + + +#if defined(__GNUC__) + /* nothing */ +#else + #pragma pack(push) + #pragma pack(1) +#endif +struct STIO_PACKED stio_ethaddr_t +{ + stio_uint8_t v[STIO_ETHADDR_LEN]; +}; +typedef struct stio_ethaddr_t stio_ethaddr_t; + +struct STIO_PACKED stio_ip4addr_t +{ + stio_uint8_t v[STIO_IP4ADDR_LEN]; +}; +typedef struct stio_ip4addr_t stio_ip4addr_t; + +struct STIO_PACKED stio_ip6addr_t +{ + stio_uint8_t v[STIO_IP6ADDR_LEN]; +}; +typedef struct stio_ip6addr_t stio_ip6addr_t; + + +struct STIO_PACKED stio_ethhdr_t +{ + stio_uint8_t dest[STIO_ETHADDR_LEN]; + stio_uint8_t source[STIO_ETHADDR_LEN]; + stio_uint16_t proto; +}; +typedef struct stio_ethhdr_t stio_ethhdr_t; + +struct STIO_PACKED stio_arphdr_t +{ + stio_uint16_t htype; /* hardware type (ethernet: 0x0001) */ + stio_uint16_t ptype; /* protocol type (ipv4: 0x0800) */ + stio_uint8_t hlen; /* hardware address length (ethernet: 6) */ + stio_uint8_t plen; /* protocol address length (ipv4 :4) */ + stio_uint16_t opcode; /* operation code */ +}; +typedef struct stio_arphdr_t stio_arphdr_t; + +/* arp payload for ipv4 over ethernet */ +struct STIO_PACKED stio_etharp_t +{ + stio_uint8_t sha[STIO_ETHADDR_LEN]; /* source hardware address */ + stio_uint8_t spa[STIO_IP4ADDR_LEN]; /* source protocol address */ + stio_uint8_t tha[STIO_ETHADDR_LEN]; /* target hardware address */ + stio_uint8_t tpa[STIO_IP4ADDR_LEN]; /* target protocol address */ +}; +typedef struct stio_etharp_t stio_etharp_t; + +struct STIO_PACKED stio_etharp_pkt_t +{ + stio_ethhdr_t ethhdr; + stio_arphdr_t arphdr; + stio_etharp_t arppld; +}; +typedef struct stio_etharp_pkt_t stio_etharp_pkt_t; + + +struct stio_iphdr_t +{ +#if defined(STIO_ENDIAN_LITTLE) + stio_uint8_t ihl:4; + stio_uint8_t version:4; +#elif defined(STIO_ENDIAN_BIG) + stio_uint8_t version:4; + stio_uint8_t ihl:4; +#else +# UNSUPPORTED ENDIAN +#endif + stio_int8_t tos; + stio_int16_t tot_len; + stio_int16_t id; + stio_int16_t frag_off; + stio_int8_t ttl; + stio_int8_t protocol; + stio_int16_t check; + stio_int32_t saddr; + stio_int32_t daddr; + /*The options start here. */ +}; +typedef struct stio_iphdr_t stio_iphdr_t; + + +struct STIO_PACKED stio_icmphdr_t +{ + stio_uint8_t type; /* message type */ + stio_uint8_t code; /* subcode */ + stio_uint16_t checksum; + union + { + struct + { + stio_uint16_t id; + stio_uint16_t seq; + } echo; + + stio_uint32_t gateway; + + struct + { + stio_uint16_t frag_unused; + stio_uint16_t mtu; + } frag; /* path mut discovery */ + } u; +}; +typedef struct stio_icmphdr_t stio_icmphdr_t; + +#if defined(__GNUC__) + /* nothing */ +#else + #pragma pack(pop) +#endif + +/* ICMP types */ +#define STIO_ICMP_ECHO_REPLY 0 +#define STIO_ICMP_UNREACH 3 /* destination unreachable */ +#define STIO_ICMP_SOURCE_QUENCE 4 +#define STIO_ICMP_REDIRECT 5 +#define STIO_ICMP_ECHO_REQUEST 8 +#define STIO_ICMP_TIME_EXCEEDED 11 +#define STIO_ICMP_PARAM_PROBLEM 12 +#define STIO_ICMP_TIMESTAMP_REQUEST 13 +#define STIO_ICMP_TIMESTAMP_REPLY 14 +#define STIO_ICMP_INFO_REQUEST 15 +#define STIO_ICMP_INFO_REPLY 16 +#define STIO_ICMP_ADDR_MASK_REQUEST 17 +#define STIO_ICMP_ADDR_MASK_REPLY 18 + +/* Subcode for STIO_ICMP_UNREACH */ +#define STIO_ICMP_UNREACH_NET 0 +#define STIO_ICMP_UNREACH_HOST 1 +#define STIO_ICMP_UNREACH_PROTOCOL 2 +#define STIO_ICMP_UNREACH_PORT 3 +#define STIO_ICMP_UNREACH_FRAG_NEEDED 4 + +/* Subcode for STIO_ICMP_REDIRECT */ +#define STIO_ICMP_REDIRECT_NET 0 +#define STIO_ICMP_REDIRECT_HOST 1 +#define STIO_ICMP_REDIRECT_NETTOS 2 +#define STIO_ICMP_REDIRECT_HOSTTOS 3 + +/* Subcode for STIO_ICMP_TIME_EXCEEDED */ +#define STIO_ICMP_TIME_EXCEEDED_TTL 0 +#define STIO_ICMP_TIME_EXCEEDED_FRAGTIME 1 + +/* ========================================================================= */ + typedef int stio_sckfam_t; struct stio_sckaddr_t @@ -72,11 +254,6 @@ typedef struct stio_sckaddr_t stio_sckaddr_t; #endif -#define STIO_SCK_ETH_PROTO_IP4 0x0800 -#define STIO_SCK_ETH_PROTO_ARP 0x0806 -#define STIO_SCK_ETH_PROTO_8021Q 0x8100 /* 802.1Q VLAN */ -#define STIO_SCK_ETH_PROTO_IP6 0x86DD - /* ========================================================================= */ enum stio_dev_sck_ioctl_cmd_t @@ -127,6 +304,7 @@ typedef int (*stio_dev_sck_on_read_t) ( stio_iolen_t dlen, const stio_sckaddr_t* srcaddr ); + typedef int (*stio_dev_sck_on_write_t) ( stio_dev_sck_t* dev, stio_iolen_t wrlen, @@ -134,8 +312,13 @@ typedef int (*stio_dev_sck_on_write_t) ( const stio_sckaddr_t* dstaddr ); -typedef int (*stio_dev_sck_on_connect_t) (stio_dev_sck_t* dev); -typedef void (*stio_dev_sck_on_disconnect_t) (stio_dev_sck_t* dev); +typedef void (*stio_dev_sck_on_disconnect_t) ( + stio_dev_sck_t* dev +); + +typedef int (*stio_dev_sck_on_connect_t) ( + stio_dev_sck_t* dev +); enum stio_dev_sck_type_t { @@ -144,10 +327,15 @@ enum stio_dev_sck_type_t STIO_DEV_SCK_UPD4, STIO_DEV_SCK_UDP6, + /* ARP at the ethernet layer */ STIO_DEV_SCK_ARP, STIO_DEV_SCK_ARP_DGRAM, - STIO_DEV_SCK_ICMP4 + /* ICMP at the IPv4 layer */ + STIO_DEV_SCK_ICMP4, + + /* ICMP at the IPv6 layer */ + STIO_DEV_SCK_ICMP6 #if 0 STIO_DEV_SCK_RAW, /* raw L2-level packet */ @@ -161,6 +349,7 @@ struct stio_dev_sck_make_t stio_dev_sck_type_t type; stio_dev_sck_on_write_t on_write; stio_dev_sck_on_read_t on_read; + stio_dev_sck_on_disconnect_t on_disconnect; }; enum stio_dev_sck_bind_option_t @@ -195,7 +384,6 @@ enum stio_def_sck_connect_option_t }; typedef enum stio_dev_sck_connect_option_t stio_dev_sck_connect_option_t; - typedef struct stio_dev_sck_connect_t stio_dev_sck_connect_t; struct stio_dev_sck_connect_t { @@ -203,7 +391,6 @@ struct stio_dev_sck_connect_t stio_sckaddr_t remoteaddr; stio_ntime_t connect_tmout; stio_dev_sck_on_connect_t on_connect; - stio_dev_sck_on_disconnect_t on_disconnect; }; typedef struct stio_dev_sck_listen_t stio_dev_sck_listen_t; @@ -211,7 +398,6 @@ struct stio_dev_sck_listen_t { int backlogs; stio_dev_sck_on_connect_t on_connect; /* optional, but new connections are dropped immediately without this */ - stio_dev_sck_on_disconnect_t on_disconnect; /* should on_discconneted be part of on_accept_t??? */ }; typedef struct stio_dev_sck_accept_t stio_dev_sck_accept_t; @@ -352,10 +538,10 @@ STIO_EXPORT int stio_dev_sck_listen ( ); STIO_EXPORT int stio_dev_sck_write ( - stio_dev_sck_t* dev, - const void* data, - stio_iolen_t len, - void* wrctx, + stio_dev_sck_t* dev, + const void* data, + stio_iolen_t len, + void* wrctx, const stio_sckaddr_t* dstaddr ); @@ -373,7 +559,6 @@ STIO_EXPORT int stio_dev_sck_timedwrite ( static STIO_INLINE void stio_dev_sck_halt (stio_dev_sck_t* sck) { stio_dev_halt ((stio_dev_t*)sck); - } static STIO_INLINE int stio_dev_sck_read (stio_dev_sck_t* sck, int enabled) @@ -386,10 +571,17 @@ static STIO_INLINE int stio_dev_sck_read (stio_dev_sck_t* sck, int enabled) #define stio_dev_sck_halt(sck) stio_dev_halt((stio_dev_t*)sck) #define stio_dev_sck_read(sck,enabled) stio_dev_read((stio_dev_t*)sck, enabled) - #endif + + +STIO_EXPORT stio_uint16_t stio_checksumip ( + const void* hdr, + stio_size_t len +); + + #ifdef __cplusplus } #endif diff --git a/stio/lib/stio.h b/stio/lib/stio.h index b1e2354..df9de78 100644 --- a/stio/lib/stio.h +++ b/stio/lib/stio.h @@ -125,15 +125,30 @@ enum stio_stopreq_t }; typedef enum stio_stopreq_t stio_stopreq_t; -typedef struct stio_tmrjob_t stio_tmrjob_t; +/* ========================================================================= */ + +#define STIO_TMRIDX_INVALID ((stio_tmridx_t)-1) + typedef stio_size_t stio_tmridx_t; +typedef struct stio_tmrjob_t stio_tmrjob_t; + typedef void (*stio_tmrjob_handler_t) ( stio_t* stio, const stio_ntime_t* now, stio_tmrjob_t* tmrjob ); +struct stio_tmrjob_t +{ + void* ctx; + stio_ntime_t when; + stio_tmrjob_handler_t handler; + stio_tmridx_t* idxptr; /* pointer to the index holder */ +}; + +/* ========================================================================= */ + struct stio_dev_mth_t { /* ------------------------------------------------------------------ */ @@ -306,102 +321,6 @@ enum stio_dev_event_t typedef enum stio_dev_event_t stio_dev_event_t; - -/* ========================================================================= */ -/* TOOD: move these to a separte file */ - -#define STIO_ETHHDR_PROTO_IP4 0x0800 -#define STIO_ETHHDR_PROTO_ARP 0x0806 - -#define STIO_ARPHDR_OPCODE_REQUEST 1 -#define STIO_ARPHDR_OPCODE_REPLY 2 - -#define STIO_ARPHDR_HTYPE_ETH 0x0001 -#define STIO_ARPHDR_PTYPE_IP4 0x0800 - -#define STIO_ETHADDR_LEN 6 -#define STIO_IP4ADDR_LEN 4 -#define STIO_IP6ADDR_LEN 16 - - -#if defined(__GNUC__) -# define STIO_PACKED __attribute__((__packed__)) - -#else -# define STIO_PACKED -# STIO_PACK_PUSH pack(push) -# STIO_PACK_PUSH pack(push) -# STIO_PACK(x) pack(x) -#endif - - -#if defined(__GNUC__) - /* nothing */ -#else - #pragma pack(push) - #pragma pack(1) -#endif -struct STIO_PACKED stio_ethaddr_t -{ - stio_uint8_t v[STIO_ETHADDR_LEN]; -}; -typedef struct stio_ethaddr_t stio_ethaddr_t; - -struct STIO_PACKED stio_ip4addr_t -{ - stio_uint8_t v[STIO_IP4ADDR_LEN]; -}; -typedef struct stio_ip4addr_t stio_ip4addr_t; - -struct STIO_PACKED stio_ip6addr_t -{ - stio_uint8_t v[STIO_IP6ADDR_LEN]; -}; -typedef struct stio_ip6addr_t stio_ip6addr_t; - - -struct STIO_PACKED stio_ethhdr_t -{ - stio_uint8_t dest[STIO_ETHADDR_LEN]; - stio_uint8_t source[STIO_ETHADDR_LEN]; - stio_uint16_t proto; -}; -typedef struct stio_ethhdr_t stio_ethhdr_t; - -struct STIO_PACKED stio_arphdr_t -{ - stio_uint16_t htype; /* hardware type (ethernet: 0x0001) */ - stio_uint16_t ptype; /* protocol type (ipv4: 0x0800) */ - stio_uint8_t hlen; /* hardware address length (ethernet: 6) */ - stio_uint8_t plen; /* protocol address length (ipv4 :4) */ - stio_uint16_t opcode; /* operation code */ -}; -typedef struct stio_arphdr_t stio_arphdr_t; - -/* arp payload for ipv4 over ethernet */ -struct STIO_PACKED stio_etharp_t -{ - stio_uint8_t sha[STIO_ETHADDR_LEN]; /* source hardware address */ - stio_uint8_t spa[STIO_IP4ADDR_LEN]; /* source protocol address */ - stio_uint8_t tha[STIO_ETHADDR_LEN]; /* target hardware address */ - stio_uint8_t tpa[STIO_IP4ADDR_LEN]; /* target protocol address */ -}; -typedef struct stio_etharp_t stio_etharp_t; - -struct STIO_PACKED stio_etharp_pkt_t -{ - stio_ethhdr_t ethhdr; - stio_arphdr_t arphdr; - stio_etharp_t arppld; -}; -typedef struct stio_etharp_pkt_t stio_etharp_pkt_t; - -#if defined(__GNUC__) - /* nothing */ -#else - #pragma pack(pop) -#endif - /* ========================================================================= */ #ifdef __cplusplus @@ -469,8 +388,8 @@ STIO_EXPORT int stio_dev_watch ( ); STIO_EXPORT int stio_dev_read ( - stio_dev_t* dev, - int enabled + stio_dev_t* dev, + int enabled ); /** @@ -504,7 +423,6 @@ STIO_EXPORT void stio_dev_halt ( stio_dev_t* dev ); - /* ========================================================================= */ #define stio_inittime(x,s,ns) (((x)->sec = (s)), ((x)->nsec = (ns)))