diff --git a/qse/cmd/http/ursd.c b/qse/cmd/http/ursd.c index 28c22d36..b0e0aea9 100644 --- a/qse/cmd/http/ursd.c +++ b/qse/cmd/http/ursd.c @@ -75,7 +75,7 @@ struct urs_hdr_t qse_uint16_t seq; /* in network-byte order */ qse_uint16_t rcode; /* response code */ qse_uint32_t urlsum;/* checksum of url in the request */ - qse_uint16_t urllen; /* url length in network-byte order */ + qse_uint16_t pktlen; /* url length in network-byte order */ }; struct urs_pkt_t @@ -85,8 +85,16 @@ struct urs_pkt_t }; #include -typedef struct xpio_t xpio_t; +typedef struct xreq_t xreq_t; +struct xreq_t +{ + qse_skad_t from; + qse_sck_len_t fromlen; + qse_uint8_t* data; + xreq_t* next; +}; +typedef struct xpio_t xpio_t; struct xpio_t { qse_pio_t* pio; @@ -110,11 +118,14 @@ struct ursd_t qse_size_t nfree; xpio_t* xpios; - xpio_t* free; - xpio_t* busy; + xpio_t* free_xpio; + xpio_t* busy_xpio; qse_sck_hnd_t sck; qse_mux_t* mux; + + xreq_t* head; + xreq_t* tail; }; @@ -135,16 +146,16 @@ static void chain_to_free_list (ursd_t* ursd, xpio_t* xpio) { xpio->busy = 0; xpio->prev = QSE_NULL; - xpio->next = ursd->free; - if (ursd->free) ursd->free->prev = xpio; - ursd->free = xpio; + xpio->next = ursd->free_xpio; + if (ursd->free_xpio) ursd->free_xpio->prev = xpio; + ursd->free_xpio = xpio; ursd->nfree++; } static xpio_t* dechain_from_free_list (ursd_t* ursd, xpio_t* xpio) { if (xpio->next) xpio->next->prev = xpio->prev; - if (xpio == ursd->free) ursd->free = xpio->next; + if (xpio == ursd->free_xpio) ursd->free_xpio = xpio->next; else xpio->prev->next = xpio->next; ursd->nfree--; return xpio; @@ -154,21 +165,26 @@ static void chain_to_busy_list (ursd_t* ursd, xpio_t* xpio) { xpio->busy = 1; xpio->prev = QSE_NULL; - xpio->next = ursd->busy; - if (ursd->busy) ursd->busy->prev = xpio; - ursd->busy = xpio; + xpio->next = ursd->busy_xpio; + if (ursd->busy_xpio) ursd->busy_xpio->prev = xpio; + ursd->busy_xpio = xpio; } static xpio_t* dechain_from_busy_list (ursd_t* ursd, xpio_t* xpio) { if (xpio->next) xpio->next->prev = xpio->prev; - if (xpio == ursd->busy) ursd->busy = xpio->next; + if (xpio == ursd->busy_xpio) ursd->busy_xpio = xpio->next; else xpio->prev->next = xpio->next; return xpio; } +static xreq_t* enqueue_request (ursd_t* ursd, urs_pkt_t* pkt) +{ + return QSE_NULL; +} + static int insert_to_mux (qse_mux_t* mux, qse_mux_hnd_t handle, int type, int index) { qse_mux_evt_t evt; @@ -191,15 +207,16 @@ static int delete_from_mux (qse_mux_t* mux, qse_mux_hnd_t handle, int type, int return qse_mux_delete (mux, &evt); } -static qse_sck_hnd_t open_server_socket (int type, int proto, const qse_nwad_t* bindnwad) +static qse_sck_hnd_t open_server_socket (int proto, const qse_nwad_t* bindnwad) { qse_sck_hnd_t s = QSE_INVALID_SCKHND; qse_skad_t skad; qse_sck_len_t skad_len; - int family, flag; + int family, type, flag; skad_len = qse_nwadtoskad (bindnwad, &skad); family = qse_skadfamily(&skad); + type = (proto == IPPROTO_SCTP)? SOCK_SEQPACKET: SOCK_DGRAM; s = socket (family, type, proto); if (!qse_isvalidsckhnd(s)) @@ -237,10 +254,11 @@ static qse_sck_hnd_t open_server_socket (int type, int proto, const qse_nwad_t* bind_ok: if (proto == IPPROTO_SCTP) { -#if 0 +#if 1 struct sctp_initmsg im; + struct sctp_paddrparams hb; - memset (&im, 0, QSE_SIZEOF(im)); + qse_memset (&im, 0, QSE_SIZEOF(im)); im.sinit_num_ostreams = 1; im.sinit_max_instreams = 1; im.sinit_max_attempts = 1; @@ -250,6 +268,13 @@ bind_ok: fprintf (stderr, "cannot set sctp initmsg option\n"); goto oops; } + + qse_memset (&hb, 0, QSE_SIZEOF(hb)); + hb.spp_flags = SPP_HB_ENABLE; + hb.spp_hbinterval = 5000; + hb.spp_pathmaxrxt = 1; + + if (setsockopt (s, SOL_SCTP, SCTP_PEER_ADDR_PARAMS, &hb, QSE_SIZEOF(hb)) <= -1) goto oops; #endif if (listen (s, 99) <= -1) @@ -266,18 +291,18 @@ oops: return QSE_INVALID_SCKHND; } -static void schedule_request (ursd_t* ursd, urs_pkt_t* pkt, int pktsize, const qse_skad_t* skad, qse_sck_len_t skadlen) +static void schedule_request (ursd_t* ursd, urs_pkt_t* pkt, const qse_skad_t* skad, qse_sck_len_t skadlen) { - if (ursd->free) + if (ursd->free_xpio) { - xpio_t* xpio = dechain_from_free_list (ursd, ursd->free); + xpio_t* xpio = dechain_from_free_list (ursd, ursd->free_xpio); xpio->req.from = *skad; xpio->req.fromlen = skadlen; - memcpy (xpio->req.buf, pkt, QSE_SIZEOF(urs_hdr_t)); /* copy header */ -printf ("XPIO WRITNG TO PIPE %p %d\n", xpio, qse_skadfamily(skad)); - qse_pio_write (xpio->pio, QSE_PIO_IN, pkt->url, qse_ntoh16(pkt->hdr.urllen)); /* TODO: erro ahndlig */ + qse_memcpy (xpio->req.buf, pkt, QSE_SIZEOF(urs_hdr_t)); /* copy header */ +printf ("XPIO WRITNG TO PIPE %p %d\n", xpio, qse_skadfamily(skad)); + qse_pio_write (xpio->pio, QSE_PIO_IN, pkt->url, pkt->hdr.pktlen - QSE_SIZEOF(urs_hdr_t)); /* TODO: error handling */ chain_to_busy_list (ursd, xpio); } else @@ -306,17 +331,20 @@ static void dispatch_mux_event (qse_mux_t* mux, const qse_mux_evt_t* evt) { ssize_t x; + skad_len = QSE_SIZEOF(skad); x = recvfrom (evt->hnd, buf, QSE_SIZEOF(buf), 0, (struct sockaddr*)&skad, &skad_len); + +printf ("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx\n"); /* TODO: error handling */ if (x >= QSE_SIZEOF(urs_hdr_t)) { urs_pkt_t* pkt = (urs_pkt_t*)buf; - qse_uint16_t len = qse_ntoh16(pkt->hdr.urllen); - if (QSE_SIZEOF(urs_hdr_t) + len == x) + pkt->hdr.pktlen = qse_ntoh16(pkt->hdr.pktlen); /* change the byte order */ + if (pkt->hdr.pktlen == x) { - printf ("%d %d [[[%s]]]\n", len, x, pkt->url); - schedule_request (mux_xtn->ursd, pkt, x, &skad, skad_len); + printf ("%d [[[%.*s]]]\n", (int)x, (int)(pkt->hdr.pktlen - QSE_SIZEOF(urs_hdr_t)), pkt->url); + schedule_request (mux_xtn->ursd, pkt, &skad, skad_len); } } } @@ -326,21 +354,36 @@ static void dispatch_mux_event (qse_mux_t* mux, const qse_mux_evt_t* evt) urs_pkt_t* pkt; xpio_t* xpio = &mux_xtn->ursd->xpios[index]; - pkt = (urs_pkt_t*)xpio->req.buf; -printf ("XPIO READING TO PIPE %p\n", xpio); - x = qse_pio_read (xpio->pio, QSE_PIO_OUT, pkt->url, QSE_SIZEOF(xpio->req.buf) - QSE_SIZEOF(urs_hdr_t)); - - pkt->hdr.urllen = qse_hton16(x); -printf ("READ %d bytes from pipes [%s]\n", x, pkt->url); - sendto (mux_xtn->ursd->sck, pkt, QSE_SIZEOF(urs_hdr_t) + x, 0, &xpio->req.from, xpio->req.fromlen); - -/* TODO: error handling */ - if (xpio->busy) { + pkt = (urs_pkt_t*)xpio->req.buf; + + x = qse_pio_read (xpio->pio, QSE_PIO_OUT, pkt->url, QSE_SIZEOF(xpio->req.buf) - QSE_SIZEOF(urs_hdr_t)); +printf ("READ %d bytes from pipes [%.*s]\n", (int)x, (int)x, pkt->url); + + x += QSE_SIZEOF(urs_hdr_t); /* add up the header size */ + if (x > QSE_TYPE_MAX(qse_uint16_t)) + { + /* ERROR HANDLING - it's returning too long data */ + } + + pkt->hdr.pktlen = qse_hton16(x); /* change the byte order */ + sendto (mux_xtn->ursd->sck, pkt, x, 0, (struct sockaddr*)&xpio->req.from, xpio->req.fromlen); + + /* TODO: error handling */ + + /* TODO: if there is a pending request, use this xpio to send request... */ + dechain_from_busy_list (mux_xtn->ursd, xpio); chain_to_free_list (mux_xtn->ursd, xpio); } + else + { + /* something is wrong. if the child process writes something + * while it's not given any input. restart this process */ + + /* TODO: */ + } } } @@ -365,7 +408,7 @@ static int init_ursd (ursd_t* ursd, int npios, const qse_char_t* cmdline, const goto oops; } - ursd->sck = open_server_socket (SOCK_SEQPACKET, IPPROTO_SCTP, &bindnwad); + ursd->sck = open_server_socket (/*IPPROTO_SCTP*/IPPROTO_UDP, &bindnwad); ursd->xpios = calloc (npios, QSE_SIZEOF(xpio_t)); if (ursd->xpios == QSE_NULL) @@ -508,7 +551,6 @@ int qse_main (int argc, qse_achar_t* argv[]) qse_closestdsios (); - #if defined(_WIN32) WSACleanup (); #endif diff --git a/qse/lib/cmn/mem.c b/qse/lib/cmn/mem.c index 0ce0482f..d9fc579c 100644 --- a/qse/lib/cmn/mem.c +++ b/qse/lib/cmn/mem.c @@ -85,8 +85,91 @@ void* qse_memcpy (void* dst, const void* src, qse_size_t n) while (n-- > 0) *d++ = *s++; return dst; -#else +#elif defined(__GNUC__) && (defined(__x86_64) || defined(__amd64)) + /* i don't really care about alignments for x86-64 at this moment. fix it later */ + + __asm__ volatile ( + "cld\n\t" + "rep movsq\n" + : /* no output */ + :"D" (dst), "S" (src), "c" (n >> 3) /* input: %rdi = d, %rsi = src, %rcx = n / 8 */ + :"memory" + ); + + __asm__ volatile ( + "rep movsb\n" + : /* no output */ + :"c" (n & 7) /* %rcx = n % 8, use existing %rdi and %rsi */ + :"memory", "%rdi", "%rsi" + ); + + return dst; + + #if 0 + qse_byte_t* d = dst; + + __asm__ volatile ( + "cld\n\t" + "rep movsq\n" + : "=D" (d), "=S" (src) /* output: d = %rdi, src = %rsi */ + :"0" (d), "1" (src), "c" (n >> 3) /* input: %rdi = d, %rsi = src, %rcx = n / 8 */ + :"memory" + ); + + __asm__ volatile ( + "rep movsb" + : /* no output */ + :"D" (d), "S" (src), "c" (n & 7) /* input: %rdi = d, %rsi = src, %rcx = n % 8 */ + :"memory" + ); + + return dst; + #endif + +#elif defined(__GNUC__) && (defined(__i386) || defined(i386)) + + /* i don't really care about alignments for x86 at this moment. fix it later */ + + __asm__ volatile ( + "cld\n\t" + "rep movsl\n" + : /* no output */ + :"D" (dst), "S" (src), "c" (n >> 2) /* input: %edi = d, %esi = src, %ecx = n / 8 */ + :"memory" + ); + + __asm__ volatile ( + "rep movsb\n" + : /* no output */ + :"c" (n & 3) /* %rcx = n % 8, use existing %edi and %esi */ + :"memory", "%edi", "%esi" + ); + + return dst; + + #if 0 + qse_byte_t* d = dst; + + __asm__ volatile ( + "cld\n\t" + "rep movsl\n" + :"=D" (d), "=S" (src) /* output: d = %edi, src = %esi */ + :"0" (d), "1" (src), "c" (n >> 2) /* input: %edi = d, %esi = src, %ecx = n / 4 */ + :"memory" + ); + + __asm__ volatile ( + "rep movsb\n" + : + :"D" (d), "S" (src), "c" (n & 3) /* input: %edi = d, %esi = src, %ecx = n % 4 */ + :"memory" + ); + + return dst; + #endif + +#else qse_byte_t* d; qse_byte_t* s; @@ -207,8 +290,81 @@ void* qse_memset (void* dst, int val, qse_size_t n) while (n-- > 0) *d++ = (qse_byte_t)val; return dst; -#else +#elif defined(__GNUC__) && (defined(__x86_64) || defined(__amd64)) + /* i don't really care about alignments for x86-64 at this moment. fix it later */ + + qse_byte_t* d = dst; + + __asm__ volatile ("cld\n"); + + if (n >= 8) + { + qse_size_t qw = (qse_byte_t)val; + if (qw) + { + qw = (qw << 8) | (qse_byte_t)val; + qw = (qw << 8) | (qse_byte_t)val; + qw = (qw << 8) | (qse_byte_t)val; + qw = (qw << 8) | (qse_byte_t)val; + qw = (qw << 8) | (qse_byte_t)val; + qw = (qw << 8) | (qse_byte_t)val; + qw = (qw << 8) | (qse_byte_t)val; + } + + __asm__ volatile ( + "rep stosq\n" + :"=D" (d) /* output: d = %rdi */ + :"0" (d), "a" (qw), "c" (n >> 3) /* input: %rdi = d, %rax = qw, %rcx = n / 8 */ + :"memory" + ); + } + + __asm__ volatile ( + "rep stosb\n" + : /* no output */ + :"D" (d), "a" (val), "c" (n & 7) /* input: %rdi = d, %rax = src, %rcx = n % 8 */ + :"memory" + ); + + return dst; + +#elif defined(__GNUC__) && (defined(__i386) || defined(i386)) + + /* i don't really care about alignments for x86 at this moment. fix it later */ + + qse_byte_t* d = dst; + + __asm__ volatile ("cld\n"); + + if (n >= 4) + { + qse_size_t dw = (qse_byte_t)val; + if (dw) + { + dw = (dw << 8) | (qse_byte_t)val; + dw = (dw << 8) | (qse_byte_t)val; + dw = (dw << 8) | (qse_byte_t)val; + } + + __asm__ volatile ( + "rep stosl\n" + :"=D" (d) /* output: d = %edi */ + :"0" (d), "a" (dw), "c" (n >> 2) /* input: %edi = d, %eax = dw, %ecx = n / 4 */ + :"memory" + ); + } + + __asm__ volatile ( + "rep stosb\n" + : /* no output */ + :"D" (d), "a" (val), "c" (n & 3) /* input: %edi = d, %eax = src, %ecx = n % 4 */ + :"memory" + ); + + return dst; + +#else qse_byte_t* d; qse_size_t rem; diff --git a/qse/lib/http/httpd-std-urs.h b/qse/lib/http/httpd-std-urs.h index af1471df..b12d6d49 100644 --- a/qse/lib/http/httpd-std-urs.h +++ b/qse/lib/http/httpd-std-urs.h @@ -36,7 +36,7 @@ struct urs_hdr_t qse_uint16_t seq; /* in network-byte order */ qse_uint16_t rcode; /* response code */ qse_uint32_t urlsum; /* checksum of url in the request */ - qse_uint16_t urllen; /* url length in network-byte order */ + qse_uint16_t pktlen; /* packet header size + url length */ }; struct urs_pkt_t @@ -59,8 +59,8 @@ struct urs_ctx_t urs_req_t* reqs[1024]; /* TOOD: choose the right size */ qse_uint16_t req_count; - qse_uint8_t rcvbuf[URS_MAX_URL_LEN + QSE_SIZEOF(urs_pkt_t)]; - qse_uint8_t fmtbuf[URS_MAX_URL_LEN + QSE_SIZEOF(urs_pkt_t)]; + qse_uint8_t rcvbuf[QSE_SIZEOF(urs_hdr_t) + URS_MAX_URL_LEN + 1]; + qse_uint8_t fmtbuf[QSE_SIZEOF(urs_hdr_t) + URS_MAX_URL_LEN + 1]; }; struct urs_req_t @@ -95,7 +95,7 @@ static int urs_open (qse_httpd_t* httpd, qse_httpd_urs_t* urs) qse_nwad_t nwad; urs_ctx_t* dc; httpd_xtn_t* httpd_xtn; - int type, proto = IPPROTO_SCTP; + int type, proto = IPPROTO_UDP; //IPPROTO_SCTP; httpd_xtn = qse_httpd_getxtn (httpd); @@ -147,12 +147,14 @@ static int urs_open (qse_httpd_t* httpd, qse_httpd_urs_t* urs) dc->urs_socket = QSE_INVALID_SCKHND; } +#if 0 if (proto == IPPROTO_SCTP) { /* TODO: error ahndleing */ if (qse_isvalidsckhnd(urs->handle[0].i)) listen (urs->handle[0].i, 99); if (qse_isvalidsckhnd(urs->handle[1].i)) listen (urs->handle[1].i, 99); } +#endif urs->handle_count = 2; urs->ctx = dc; @@ -215,7 +217,7 @@ static int urs_recv (qse_httpd_t* httpd, qse_httpd_urs_t* urs, qse_ubi_t handle) socklen_t fromlen; qse_uint16_t xid; - qse_ssize_t len; + qse_ssize_t len, url_len; urs_pkt_t* pkt; urs_req_t* req; @@ -229,29 +231,34 @@ printf ("URS_RECV....\n"); /* TODO: check if fromaddr matches the dc->skad... */ pkt = (urs_pkt_t*)dc->rcvbuf; - if (len >= QSE_SIZEOF(pkt->hdr) && len >= QSE_SIZEOF(pkt->hdr) + qse_ntoh16(pkt->hdr.urllen)) + if (len >= QSE_SIZEOF(urs_hdr_t)) { - xid = qse_ntoh16(pkt->hdr.seq) % QSE_COUNTOF(dc->reqs); - - for (req = dc->reqs[xid]; req; req = req->next) + pkt->hdr.pktlen = qse_ntoh16(pkt->hdr.pktlen); + if (len == pkt->hdr.pktlen) { - if (req->pkt->hdr.seq == pkt->hdr.seq && req->pkt->hdr.urlsum == pkt->hdr.urlsum) + url_len = pkt->hdr.pktlen - QSE_SIZEOF(urs_hdr_t); + xid = qse_ntoh16(pkt->hdr.seq) % QSE_COUNTOF(dc->reqs); + + for (req = dc->reqs[xid]; req; req = req->next) { - /* null-terminate the url for easier processing */ - pkt->url[qse_ntoh16(pkt->hdr.urllen)] = QSE_MT('\0'); + if (req->pkt->hdr.seq == pkt->hdr.seq && req->pkt->hdr.urlsum == pkt->hdr.urlsum) + { + /* null-terminate the url for easier processing */ + pkt->url[url_len] = QSE_MT('\0'); - urs_remove_tmr_tmout (httpd, req); - req->rewrite (httpd, req->pkt->url, pkt->url, req->ctx); + urs_remove_tmr_tmout (httpd, req); + req->rewrite (httpd, req->pkt->url, pkt->url, req->ctx); - /* detach the request off dc->reqs */ - if (req == dc->reqs[xid]) dc->reqs[xid] = req->next; - else req->prev->next = req->next; - if (req->next) req->next->prev = req->prev; + /* detach the request off dc->reqs */ + if (req == dc->reqs[xid]) dc->reqs[xid] = req->next; + else req->prev->next = req->next; + if (req->next) req->next->prev = req->prev; - qse_httpd_freemem (httpd, req); - dc->req_count--; + qse_httpd_freemem (httpd, req); + dc->req_count--; - break; + break; + } } } } @@ -362,21 +369,19 @@ static int urs_send (qse_httpd_t* httpd, qse_httpd_urs_t* urs, const qse_mchar_t xid = seq % QSE_COUNTOF(dc->reqs); - req = qse_httpd_callocmem (httpd, QSE_SIZEOF(*req) + url_len + QSE_SIZEOF(urs_pkt_t)); + req = qse_httpd_callocmem (httpd, QSE_SIZEOF(*req) + QSE_SIZEOF(urs_hdr_t) + url_len + 1); if (req == QSE_NULL) goto oops; req->tmr_tmout = QSE_TMR_INVALID_INDEX; req->seq = seq; req->pkt = (urs_pkt_t*)(req + 1); + req->pktlen = QSE_SIZEOF(urs_hdr_t) + url_len; req->pkt->hdr.seq = qse_hton16(seq); - req->pkt->hdr.urllen = qse_hton16(url_len); + req->pkt->hdr.pktlen = qse_hton16(req->pktlen); req->pkt->hdr.urlsum = hash_string (url); qse_mbscpy (req->pkt->url, url); - /* -1 to exclude the terminating '\0' as urs_pkt_t has url[1]. */ - req->pktlen = QSE_SIZEOF(urs_pkt_t) + url_len - 1; - req->rewrite = rewrite; req->ctx = ctx; diff --git a/qse/lib/http/httpd-std.c b/qse/lib/http/httpd-std.c index 3a886215..eaa8aa8e 100644 --- a/qse/lib/http/httpd-std.c +++ b/qse/lib/http/httpd-std.c @@ -730,10 +730,11 @@ static qse_sck_hnd_t open_udp_socket (qse_httpd_t* httpd, int domain, int type, if (set_socket_nonblock (httpd, fd, 1) <= -1) goto oops; - +#if 1 if (proto == IPPROTO_SCTP) { struct sctp_initmsg im; + struct sctp_paddrparams hb; QSE_MEMSET (&im, 0, QSE_SIZEOF(im)); im.sinit_num_ostreams = 1; @@ -741,7 +742,15 @@ static qse_sck_hnd_t open_udp_socket (qse_httpd_t* httpd, int domain, int type, im.sinit_max_attempts = 1; if (setsockopt (fd, SOL_SCTP, SCTP_INITMSG, &im, QSE_SIZEOF(im)) <= -1) goto oops; + + QSE_MEMSET (&hb, 0, QSE_SIZEOF(hb)); + hb.spp_flags = SPP_HB_ENABLE; + hb.spp_hbinterval = 5000; + hb.spp_pathmaxrxt = 1; + + if (setsockopt (fd, SOL_SCTP, SCTP_PEER_ADDR_PARAMS, &hb, QSE_SIZEOF(hb)) <= -1) goto oops; } +#endif return fd;