--- libaitrpc/src/srv.c 2013/07/16 13:04:20 1.17 +++ libaitrpc/src/srv.c 2013/08/22 15:31:09 1.18 @@ -3,7 +3,7 @@ * by Michael Pounov * * $Author: misho $ -* $Id: srv.c,v 1.17 2013/07/16 13:04:20 misho Exp $ +* $Id: srv.c,v 1.18 2013/08/22 15:31:09 misho Exp $ * ************************************************************************** The ELWIX and AITNET software is distributed under the following @@ -161,24 +161,29 @@ txPacket(sched_task_t *task) rpc_cli_t *c = TASK_ARG(task); rpc_srv_t *s = c->cli_parent; rpc_func_t *f = NULL; - u_char buf[USHRT_MAX] = { 0 }; + u_char *buf = AIT_GET_BUF(&c->cli_buf); struct tagRPCCall *rpc = (struct tagRPCCall*) buf; - int ret, wlen = sizeof(struct tagRPCCall); + int ret, estlen, wlen = sizeof(struct tagRPCCall); - /* copy RPC header */ - memcpy(buf, TASK_DATA(task), wlen); - if (rpc->call_argc) { f = rpc_srv_getCall(s, ntohs(rpc->call_tag)); if (!f) { rpc_SetErr(EPROGUNAVAIL, "Function not found at RPC server"); + rpc->call_argc ^= rpc->call_argc; rpc->call_rep.ret = RPC_ERROR(-1); rpc->call_rep.eno = RPC_ERROR(rpc_Errno); } else { + /* calc estimated length */ + estlen = ait_resideVars(RPC_RETVARS(c)) + wlen; + if (estlen > AIT_LEN(&c->cli_buf)) + AIT_RE_BUF(&c->cli_buf, estlen); + buf = AIT_GET_BUF(&c->cli_buf); + rpc->call_argc = htons(array_Size(RPC_RETVARS(c))); /* Go Encapsulate variables */ - ret = ait_vars2buffer(buf + wlen, sizeof buf - wlen, RPC_RETVARS(c)); + ret = ait_vars2buffer(buf + wlen, AIT_LEN(&c->cli_buf) - wlen, + RPC_RETVARS(c)); /* Free return values */ ait_freeVars(&c->cli_vars); if (ret == -1) { @@ -191,7 +196,7 @@ txPacket(sched_task_t *task) } } - rpc->call_len = htons(wlen); + rpc->call_len = htonl(wlen); #if 0 /* calculate CRC */ @@ -217,17 +222,17 @@ execCall(sched_task_t *task) rpc_srv_t *s = c->cli_parent; rpc_func_t *f = NULL; array_t *arr = NULL; - u_char *buf = AIT_GET_BUF(&c->cli_buf) + TASK_VAL(task); + u_char *buf = AIT_GET_BUF(&c->cli_buf); struct tagRPCCall *rpc = (struct tagRPCCall*) buf; int argc = ntohs(rpc->call_argc); /* Go decapsulate variables ... */ if (argc) { arr = ait_buffer2vars(buf + sizeof(struct tagRPCCall), - AIT_LEN(&c->cli_buf) - TASK_VAL(task) - sizeof(struct tagRPCCall), - argc, 42); + AIT_LEN(&c->cli_buf) - sizeof(struct tagRPCCall), argc, 42); if (!arr) { rpc_SetErr(ERPCMISMATCH, "#%d - %s", elwix_GetErrno(), elwix_GetError()); + rpc->call_argc ^= rpc->call_argc; rpc->call_rep.ret = RPC_ERROR(-1); rpc->call_rep.eno = RPC_ERROR(rpc_Errno); @@ -238,6 +243,7 @@ execCall(sched_task_t *task) if (!(f = rpc_srv_getCall(s, ntohs(rpc->call_tag)))) { rpc_SetErr(EPROGUNAVAIL, "Function not found at RPC server"); + rpc->call_argc ^= rpc->call_argc; rpc->call_rep.ret = RPC_ERROR(-1); rpc->call_rep.eno = RPC_ERROR(rpc_Errno); @@ -270,85 +276,72 @@ rxPacket(sched_task_t *task) { rpc_cli_t *c = TASK_ARG(task); rpc_srv_t *s = c->cli_parent; - int len, rlen, noreply; - u_short off = TASK_DATLEN(task); + int len, rlen, noreply, estlen; #if 0 u_short crc; #endif u_char *buf = AIT_GET_BUF(&c->cli_buf); - struct tagRPCCall *rpc; + struct tagRPCCall *rpc = (struct tagRPCCall*) buf; - if (!off) - memset(buf, 0, AIT_LEN(&c->cli_buf)); - rlen = recv(TASK_FD(task), buf + off, AIT_LEN(&c->cli_buf) - off, 0); - if (rlen < 1) { + memset(buf, 0, sizeof(struct tagRPCCall)); + rlen = recv(TASK_FD(task), rpc, sizeof(struct tagRPCCall), 0); + if (rlen < sizeof(struct tagRPCCall)) { /* close connection */ schedEvent(TASK_ROOT(task), cbProto[s->srv_proto][CB_CLOSECLIENT], TASK_ARG(task), 0, NULL, 0); return NULL; } else { - rlen += off; /* add reminded bytes from previous rxPacket, if exists! */ - off = 0; /* process buffer from start offset == 0 */ + estlen = ntohl(rpc->call_len); + if (estlen > AIT_LEN(&c->cli_buf)) + AIT_RE_BUF(&c->cli_buf, estlen); + rpc = (struct tagRPCCall*) AIT_GET_BUF(&c->cli_buf); + buf = AIT_GET_BUF(&c->cli_buf) + sizeof(struct tagRPCCall); + len = estlen - sizeof(struct tagRPCCall); } - do { - /* check RPC packet */ - if (rlen < sizeof(struct tagRPCCall)) { - rpc_SetErr(ERPCMISMATCH, "Short RPC packet"); - - /* reminder received previous bytes ;) */ - schedRead(TASK_ROOT(task), TASK_FUNC(task), TASK_ARG(task), - TASK_FD(task), TASK_DATA(task), rlen); + if (len) { + /* get next part of packet */ + memset(buf, 0, len); + rlen = recv(TASK_FD(task), buf, len, 0); + if (rlen == -1) { + /* close connection */ + schedEvent(TASK_ROOT(task), cbProto[s->srv_proto][CB_CLOSECLIENT], + TASK_ARG(task), 0, NULL, 0); return NULL; - } else - rpc = (struct tagRPCCall*) (buf + off); - - len = ntohs(rpc->call_len); - rlen -= len; - - /* check RPC packet lengths */ - if (rlen < 0 || len < sizeof(struct tagRPCCall)) { - rpc_SetErr(ERPCMISMATCH, "Broken RPC packet length"); - /* skip entire packet */ - break; } + } #if 0 - /* check integrity of packet */ - crc = ntohs(rpc->call_crc); - rpc->call_crc ^= rpc->call_crc; - if (crc != crcFletcher16((u_short*) rpc, len / 2)) { - rpc_SetErr(ERPCMISMATCH, "Bad CRC RPC packet"); - - off += len; - /* try next packet remaining into buffer */ - continue; - } + /* check integrity of packet */ + crc = ntohs(rpc->call_crc); + rpc->call_crc ^= rpc->call_crc; + if (crc != crcFletcher16((u_short*) rpc, len / 2)) { + rpc_SetErr(ERPCMISMATCH, "Bad CRC RPC packet"); + return NULL; + } #endif - noreply = RPC_CHK_NOREPLY(rpc); + noreply = RPC_CHK_NOREPLY(rpc); - /* check RPC packet session info */ - if (rpc_chkPktSession(&rpc->call_session, &s->srv_session)) { - rpc_SetErr(ERPCMISMATCH, "Get invalid RPC session"); - rpc->call_argc ^= rpc->call_argc; - rpc->call_rep.ret = RPC_ERROR(-1); - rpc->call_rep.eno = RPC_ERROR(errno); - } else { - /* execute RPC call */ - schedEvent(TASK_ROOT(task), execCall, TASK_ARG(task), off, NULL, 0); - } + /* check RPC packet session info */ + if (rpc_chkPktSession(&rpc->call_session, &s->srv_session)) { + rpc_SetErr(ERPCMISMATCH, "Get invalid RPC session"); - /* send RPC reply */ - if (!noreply) - schedWrite(TASK_ROOT(task), cbProto[s->srv_proto][CB_TXPACKET], - TASK_ARG(task), TASK_FD(task), rpc, len); + rpc->call_argc ^= rpc->call_argc; + rpc->call_rep.ret = RPC_ERROR(-1); + rpc->call_rep.eno = RPC_ERROR(errno); + } else { + /* execute RPC call */ + schedEvent(TASK_ROOT(task), execCall, TASK_ARG(task), (int) noreply, rpc, len); + } - off += len; - } while (rlen > 0); + /* send RPC reply */ + if (!noreply) + schedWrite(TASK_ROOT(task), cbProto[s->srv_proto][CB_TXPACKET], + TASK_ARG(task), TASK_FD(task), rpc, len); /* lets get next packet */ - schedRead(TASK_ROOT(task), TASK_FUNC(task), TASK_ARG(task), TASK_FD(task), TASK_DATA(task), 0); + schedReadSelf(task); return NULL; } @@ -387,7 +380,7 @@ txUDPPacket(sched_task_t *task) rpc_cli_t *c = TASK_ARG(task); rpc_srv_t *s = c->cli_parent; rpc_func_t *f = NULL; - u_char buf[USHRT_MAX] = { 0 }; + u_char *buf = AIT_GET_BUF(&c->cli_buf); struct tagRPCCall *rpc = (struct tagRPCCall*) buf; int ret, wlen = sizeof(struct tagRPCCall); struct timespec ts = { DEF_RPC_TIMEOUT, 0 }; @@ -396,9 +389,6 @@ txUDPPacket(sched_task_t *task) schedTimer(TASK_ROOT(task), cbProto[s->srv_proto][CB_CLOSECLIENT], TASK_ARG(task), ts, TASK_ARG(task), 0); - /* copy RPC header */ - memcpy(buf, TASK_DATA(task), wlen); - if (rpc->call_argc) { f = rpc_srv_getCall(s, ntohs(rpc->call_tag)); if (!f) { @@ -409,7 +399,8 @@ txUDPPacket(sched_task_t *task) } else { rpc->call_argc = htons(array_Size(RPC_RETVARS(c))); /* Go Encapsulate variables */ - ret = ait_vars2buffer(buf + wlen, sizeof buf - wlen, RPC_RETVARS(c)); + ret = ait_vars2buffer(buf + wlen, AIT_LEN(&c->cli_buf) - wlen, + RPC_RETVARS(c)); /* Free return values */ ait_freeVars(&c->cli_vars); if (ret == -1) { @@ -422,7 +413,7 @@ txUDPPacket(sched_task_t *task) } } - rpc->call_len = htons(wlen); + rpc->call_len = htonl(wlen); /* calculate CRC */ rpc->call_crc ^= rpc->call_crc; @@ -480,7 +471,7 @@ rxUDPPacket(sched_task_t *task) } else rpc = (struct tagRPCCall*) (AIT_GET_BUF(&c->cli_buf) + off); - len = ntohs(rpc->call_len); + len = ntohl(rpc->call_len); rlen -= len; /* check RPC packet lengths */ @@ -506,12 +497,14 @@ rxUDPPacket(sched_task_t *task) /* check RPC packet session info */ if (rpc_chkPktSession(&rpc->call_session, &srv->srv_session)) { rpc_SetErr(ERPCMISMATCH, "Get invalid RPC session"); + rpc->call_argc ^= rpc->call_argc; rpc->call_rep.ret = RPC_ERROR(-1); rpc->call_rep.eno = RPC_ERROR(errno); } else { /* execute RPC call */ - schedEvent(TASK_ROOT(task), execCall, c, off, NULL, 0); + schedEvent(TASK_ROOT(task), execCall, c, + (int) noreply, rpc, len); } /* send RPC reply */