/* * @in1 buffer = hep + sip * @in2 buffer length * @in3 version - needed to make the difference betwen 3 and the first 2 protos * @out1 structure containing hep details + headers | see hep.h */ int unpack_hep(char *buf, int len, int version, struct hep_desc* h) { int err; if (version == 3) err = unpack_hepv3(buf, len, h); else err = unpack_hepv2(buf, len, h); return err; }
static inline int hep_handle_req(struct tcp_req *req, struct tcp_connection *con, int _max_msg_chunks) { struct receive_info local_rcv; struct hep_desc h; char *msg_buf; int msg_len; long size; int ret=0; if (req->complete){ /* update the timeout - we successfully read the request */ tcp_conn_set_lifetime( con, tcp_con_lifetime); con->timeout=con->lifetime; /* just for debugging use sendipv4 as receiving socket FIXME*/ con->rcv.proto_reserved1=con->id; /* copy the id */ /* prepare for next request */ size=req->pos-req->parsed; msg_buf = req->start; msg_len = req->parsed-req->start; local_rcv = con->rcv; if (!size) { /* did not read any more things - we can release * the connection */ LM_DBG("Nothing more to read on TCP conn %p, currently in state %d \n", con,con->state); if (req != &hep_current_req) { /* we have the buffer in the connection tied buff - * detach it , release the conn and free it afterwards */ con->con_req = NULL; } /* TODO - we could indicate to the TCP net layer to release * the connection -> other worker may read the next available * message on the pipe */ } else { LM_DBG("We still have things on the pipe - " "keeping connection \n"); } if( msg_buf[0] == 'H' && msg_buf[1] == 'E' && msg_buf[2] == 'P' ) { /* HEP related */ if (unpack_hepv3(msg_buf, msg_len, &h)) { LM_ERR("failed to unpack hepV3\n"); return -1; } ret=run_hep_cbs(&h, &local_rcv); if (ret < 0) { LM_ERR("failed to run hep callbacks\n"); return -1; } msg_len = ntohs(h.u.hepv3.payload_chunk.chunk.length) - sizeof(hep_chunk_payload_t); /* remove the hep header; leave only the payload */ msg_buf = h.u.hepv3.payload_chunk.data; } /* skip receive msg if we were told so from at least one callback */ if (ret != HEP_SCRIPT_SKIP && receive_msg(msg_buf, msg_len, &local_rcv) <0) LM_ERR("receive_msg failed \n"); if (!size && req != &hep_current_req) { /* if we no longer need this tcp_req * we can free it now */ pkg_free(req); } if (size) { memmove(req->buf, req->parsed, size); req->pos = req->buf + size; /* anything that was parsed was already processed */ req->parsed = req->buf; } /* if we still have some unparsed bytes, try to parse them too*/ if (size) return 1; } else { /* request not complete - check the if the thresholds are exceeded */ if (con->msg_attempts==0) /* if first iteration, set a short timeout for reading * a whole SIP message */ con->timeout = get_ticks() + tcp_max_msg_time; con->msg_attempts ++; if (con->msg_attempts == _max_msg_chunks) { LM_ERR("Made %u read attempts but message is not complete yet - " "closing connection \n",con->msg_attempts); goto error; } if (req == &hep_current_req) { /* let's duplicate this - most likely another conn will come in */ LM_DBG("We didn't manage to read a full request\n"); con->con_req = pkg_malloc(sizeof(struct tcp_req)); if (con->con_req == NULL) { LM_ERR("No more mem for dynamic con request buffer\n"); goto error; } if (req->pos != req->buf) { /* we have read some bytes */ memcpy(con->con_req->buf,req->buf,req->pos-req->buf); con->con_req->pos = con->con_req->buf + (req->pos-req->buf); } else { con->con_req->pos = con->con_req->buf; } if (req->parsed != req->buf) con->con_req->parsed =con->con_req->buf+(req->parsed-req->buf); else con->con_req->parsed = con->con_req->buf; con->con_req->complete=req->complete; con->con_req->content_len=req->content_len; con->con_req->error = req->error; /* req will be reset on the next usage */ } } /* everything ok */ return 0; error: /* report error */ return -1; }
static int hep_udp_read_req(struct socket_info *si, int* bytes_read) { struct receive_info ri; int len; #ifdef DYN_BUF char* buf; #else static char buf [BUF_SIZE+1]; #endif char *tmp; unsigned int fromlen; str msg; struct hep_context *hep_ctx; int ret = 0; context_p ctx=NULL; #ifdef DYN_BUF buf=pkg_malloc(BUF_SIZE+1); if (buf==0){ LM_ERR("could not allocate receive buffer\n"); goto error; } #endif fromlen=sockaddru_len(si->su); len=recvfrom(bind_address->socket, buf, BUF_SIZE,0,&ri.src_su.s,&fromlen); if (len==-1){ if (errno==EAGAIN) return 0; if ((errno==EINTR)||(errno==EWOULDBLOCK)|| (errno==ECONNREFUSED)) return -1; LM_ERR("recvfrom:[%d] %s\n", errno, strerror(errno)); return -2; } if (len<MIN_UDP_PACKET) { LM_DBG("probing packet received len = %d\n", len); return 0; } /* we must 0-term the messages, receive_msg expects it */ buf[len]=0; /* no need to save the previous char */ ri.bind_address = si; ri.dst_port = si->port_no; ri.dst_ip = si->address; ri.proto = si->proto; ri.proto_reserved1 = ri.proto_reserved2 = 0; su2ip_addr(&ri.src_ip, &ri.src_su); ri.src_port=su_getport(&ri.src_su); /* if udp we are sure that version 1 or 2 of the * protocol is used */ if ((hep_ctx = shm_malloc(sizeof(struct hep_context))) == NULL) { LM_ERR("no more shared memory!\n"); return -1; } memset(hep_ctx, 0, sizeof(struct hep_context)); memcpy(&hep_ctx->ri, &ri, sizeof(struct receive_info)); if (len < 4) { LM_ERR("invalid message! too short!\n"); return -1; } if (!memcmp(buf, HEP_HEADER_ID, HEP_HEADER_ID_LEN)) { /* HEPv3 */ if (unpack_hepv3(buf, len, &hep_ctx->h)) { LM_ERR("hepv3 unpacking failed\n"); return -1; } } else { /* HEPv2 */ if (unpack_hepv12(buf, len, &hep_ctx->h)) { LM_ERR("hepv12 unpacking failed\n"); return -1; } } /* set context for receive_msg */ if ((ctx=context_alloc(CONTEXT_GLOBAL)) == NULL) { LM_ERR("failed to allocate new context! skipping...\n"); goto error_free_hep; } memset(ctx, 0, context_size(CONTEXT_GLOBAL)); context_put_ptr(CONTEXT_GLOBAL, ctx, hep_ctx_idx, hep_ctx); update_recv_info(&ri, &hep_ctx->h); /* run hep callbacks; set the current processing context * to hep context; this way callbacks will have all the data * needed */ current_processing_ctx = ctx; ret=run_hep_cbs(); if (ret < 0) { LM_ERR("failed to run hep callbacks\n"); return -1; } current_processing_ctx = NULL; if (hep_ctx->h.version == 3) { /* HEPv3 */ msg.len = hep_ctx->h.u.hepv3.payload_chunk.chunk.length- sizeof(hep_chunk_t); msg.s = hep_ctx->h.u.hepv3.payload_chunk.data; } else { /* HEPv12 */ msg.len = len - hep_ctx->h.u.hepv12.hdr.hp_l; msg.s = buf + hep_ctx->h.u.hepv12.hdr.hp_l; if (hep_ctx->h.u.hepv12.hdr.hp_v == 2) { msg.s += sizeof(struct hep_timehdr); msg.len -= sizeof(struct hep_timehdr); } } if (ri.src_port==0){ tmp=ip_addr2a(&ri.src_ip); LM_INFO("dropping 0 port packet for %s\n", tmp); return 0; } if (ret != HEP_SCRIPT_SKIP) { /* receive_msg must free buf too!*/ receive_msg( msg.s, msg.len, &ri, ctx); } return 0; error_free_hep: shm_free(hep_ctx); return -1; }