static void pbuf_list_append(pbuf_list *hd, struct pbuf *p) { pbuf_list *tl = hd; while (tl->next) tl=tl->next; tl->next = pbuf_list_alloc(p); }
err_t tcp_recv_cb(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { tcp_wrap *tw = (tcp_wrap *)arg; value v_unit; err_t ret_err; if (p == NULL || err != ERR_OK) { LWIP_STUB_DPRINTF("tcp_recv_cb: p==NULL || err!=ERR_OK state->CLOSING"); tw->desc->state = TCP_CLOSING; /* Wake up any listeners, which will get a read error once the pending receive queue has been handled by the application */ v_unit = caml_callback(Field(tw->v, 0), Val_unit); if (p) pbuf_free(p); ret_err = ERR_OK; } else { if (tw->desc->rx == NULL) { LWIP_STUB_DPRINTF("tcp_recv_cb: rx first packet"); tw->desc->rx = pbuf_list_alloc(p); v_unit = caml_callback(Field(tw->v, 0), Val_unit); ret_err = ERR_OK; } else if (tw->desc->state == TCP_ACCEPTED) { /* Should be no need to wake up listeners here as nothing can sleep if there are already pending packets in rx queue */ LWIP_STUB_DPRINTF("tcp_recv_cb: rx chaining packet"); pbuf_list_append(tw->desc->rx, p); ret_err = ERR_OK; } else if (tw->desc->state == TCP_CLOSING) { /* Remote side closing twice, trash the data */ tcp_recved(pcb, p->tot_len); pbuf_free(p); ret_err = ERR_OK; } else { LWIP_STUB_DPRINTF1("tcp_recv_cb: rx unknown else; state=%d", tw->desc->state); tcp_recved(pcb, p->tot_len); pbuf_free(p); ret_err = ERR_OK; } } return ret_err; }
/* Send experimenter multipart reply. */ STATIC lagopus_result_t ofp_experimenter_mp_reply_create( struct channel *channel, struct pbuf_list **pbuf_list, struct ofp_header *xid_header, struct ofp_experimenter_multipart_header *exper_req) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; uint16_t tmp_length = 0; uint16_t length = 0; struct ofp_multipart_reply mp_reply; struct pbuf *pbuf = NULL; struct ofp_experimenter_multipart_header exper_reply; if (channel != NULL && pbuf_list != NULL && xid_header != NULL && exper_req != NULL) { /* alloc */ *pbuf_list = pbuf_list_alloc(); if (*pbuf_list != NULL) { pbuf = pbuf_list_last_get(*pbuf_list); if (pbuf != NULL) { pbuf_plen_set(pbuf, pbuf_size_get(pbuf)); /* Fill in header. */ memset(&mp_reply, 0, sizeof(mp_reply)); ofp_header_set(&mp_reply.header, channel_version_get(channel), OFPT_MULTIPART_REPLY, tmp_length, xid_header->xid); mp_reply.type = OFPMP_EXPERIMENTER; mp_reply.flags = 0; /* Encode multipart reply. */ ret = ofp_multipart_reply_encode(pbuf, &mp_reply); if (ret == LAGOPUS_RESULT_OK) { exper_reply.experimenter = exper_req->experimenter; exper_reply.exp_type = exper_req->exp_type; /* Encode message. */ ret = ofp_experimenter_multipart_header_encode( pbuf, &exper_reply); if (ret == LAGOPUS_RESULT_OK) { /* set length for last pbuf. */ ret = pbuf_length_get(pbuf, &length); if (ret == LAGOPUS_RESULT_OK) { ret = ofp_header_length_set(pbuf, length); if (ret == LAGOPUS_RESULT_OK) { pbuf_plen_reset(pbuf); ret = LAGOPUS_RESULT_OK; } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("Can't allocate pbuf.\n"); ret = LAGOPUS_RESULT_NO_MEMORY; } } else { lagopus_msg_warning("Can't allocate pbuf_list.\n"); ret = LAGOPUS_RESULT_NO_MEMORY; } if (ret != LAGOPUS_RESULT_OK && *pbuf_list != NULL) { pbuf_list_free(*pbuf_list); *pbuf_list = NULL; } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
STATIC lagopus_result_t ofp_meter_features_reply_create(struct channel *channel, struct pbuf_list **pbuf_list, struct ofp_meter_features *ofp_meter_features, struct ofp_header *xid_header) { lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES; uint16_t length = 0; struct pbuf *pbuf = NULL; struct ofp_multipart_reply ofpmp_reply; /* check params */ if (channel != NULL && pbuf_list != NULL && ofp_meter_features != NULL && xid_header != NULL) { /* alloc */ *pbuf_list = NULL; *pbuf_list = pbuf_list_alloc(); if (*pbuf_list != NULL) { /* alloc&get tail of pbuf_list */ pbuf = pbuf_list_last_get(*pbuf_list); if (pbuf != NULL) { /* set data. */ memset(&ofpmp_reply, 0, sizeof(ofpmp_reply)); ofp_header_set(&ofpmp_reply.header, channel_version_get(channel), OFPT_MULTIPART_REPLY, 0, /* length set in ofp_header_length_set() */ xid_header->xid); ofpmp_reply.type = OFPMP_METER_FEATURES; /* encode message. */ pbuf_plen_set(pbuf, pbuf_size_get(pbuf)); res = ofp_multipart_reply_encode_list(*pbuf_list, &pbuf, &ofpmp_reply); if (res == LAGOPUS_RESULT_OK) { res = ofp_meter_features_encode_list(*pbuf_list, &pbuf, ofp_meter_features); if (res == LAGOPUS_RESULT_OK) { /* set packet length */ res = pbuf_length_get(pbuf, &length); if (res == LAGOPUS_RESULT_OK) { res = ofp_header_length_set(pbuf, length); if (res == LAGOPUS_RESULT_OK) { pbuf_plen_reset(pbuf); } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(res)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(res)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(res)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(res)); } } else { res = LAGOPUS_RESULT_NO_MEMORY; } } else { res = LAGOPUS_RESULT_NO_MEMORY; } } else { res = LAGOPUS_RESULT_INVALID_ARGS; } return res; }