/* Copy out all the pbufs in a chain into a string, and ack/free pbuf. * @return 0: nothing, -1: closed connection, +n: bytes read */ CAMLprim value caml_tcp_read(value v_tw) { CAMLparam1(v_tw); CAMLlocal1(v_str); /* Not using tcp_wrap_of_value as we need to clear out the remaining RX queue before raising the Connection_closed exception. Check that tw->pcb is set for the rest of the function before using it. */ tcp_wrap *tw = Tcp_wrap_val(v_tw); struct pbuf_list *pl = tw->desc->rx; unsigned int tot_len; char *s; LWIP_STUB_DPRINTF("caml_tcp_rx_read"); if (!pl) { v_str = caml_alloc_string(0); CAMLreturn(v_str); } tot_len = pbuf_list_length(pl); v_str = caml_alloc_string(tot_len); s = String_val(v_str); do { pbuf_copy_partial(pl->p, s, pl->p->tot_len, 0); s += pl->p->tot_len; } while ((pl = pl->next)); if (tw->pcb) tcp_recved(tw->pcb, tot_len); pbuf_list_free(tw->desc->rx); tw->desc->rx = NULL; CAMLreturn(v_str); }
lagopus_result_t ofp_meter_features_request_handle(struct channel *channel, struct pbuf *pbuf, struct ofp_header *xid_header, struct ofp_error *error) { lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES; uint64_t dpid; struct ofp_meter_features ofp_meter_features; struct pbuf_list *send_pbuf_list = NULL; /* check params */ if (channel != NULL && pbuf != NULL && xid_header != NULL && error != NULL) { if (pbuf_plen_equal_check(pbuf, 0) == LAGOPUS_RESULT_OK) { /* get datas */ memset(&ofp_meter_features, 0, sizeof(ofp_meter_features)); dpid = channel_dpid_get(channel); res = ofp_meter_features_get(dpid, &ofp_meter_features, error); if (res == LAGOPUS_RESULT_OK) { /* create desc reply. */ res = ofp_meter_features_reply_create(channel, &send_pbuf_list, &ofp_meter_features, xid_header); if (res == LAGOPUS_RESULT_OK) { /* send desc reply */ res = channel_send_packet_list(channel, send_pbuf_list); if (res != LAGOPUS_RESULT_OK) { lagopus_msg_warning("Socket write error (%s).\n", lagopus_error_get_string(res)); } } else { lagopus_msg_warning("reply creation failed, (%s).\n", lagopus_error_get_string(res)); } /* free. */ if (send_pbuf_list != NULL) { pbuf_list_free(send_pbuf_list); } } } else { lagopus_msg_warning("over packet length.\n"); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); res = LAGOPUS_RESULT_OFP_ERROR; } } else { res = LAGOPUS_RESULT_INVALID_ARGS; } return res; }
/* Group Features Request packet receive. */ lagopus_result_t ofp_group_features_request_handle(struct channel *channel, struct pbuf *pbuf, struct ofp_header *xid_header, struct ofp_error *error) { lagopus_result_t ret; uint64_t dpid; struct ofp_group_features group_features; struct pbuf_list *pbuf_list = NULL; if (channel != NULL && pbuf != NULL && xid_header != NULL && error != NULL) { if (pbuf_plen_equal_check(pbuf, 0) == LAGOPUS_RESULT_OK) { dpid = channel_dpid_get(channel); ret = ofp_group_features_get(dpid, &group_features, error); if (ret == LAGOPUS_RESULT_OK) { ret = ofp_group_features_reply_create(channel, &pbuf_list, &group_features, xid_header); if (ret == LAGOPUS_RESULT_OK) { /* write packets. */ ret = channel_send_packet_list(channel, pbuf_list); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("Can't write\n"); } } 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("over packet length.\n"); ofp_error_set(error, OFPET_BAD_REQUEST, OFPBRC_BAD_LEN); ret = LAGOPUS_RESULT_OFP_ERROR; } /* free. */ if (pbuf_list != NULL) { pbuf_list_free(pbuf_list); } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
static void tcp_wrap_finalize(value v_tw) { tcp_wrap *tw = Tcp_wrap_val(v_tw); LWIP_STUB_DPRINTF("tcp_wrap_finalize"); if (tw->pcb) { if (tcp_close(tw->pcb) != ERR_OK) tcp_abort(tw->pcb); tw->pcb = NULL; } if (tw->desc->rx) pbuf_list_free(tw->desc->rx); if (tw->desc) free(tw->desc); if (tw->v) caml_remove_generational_global_root(&tw->v); free(tw); }
/* Experimenter multipart packet receive. */ lagopus_result_t ofp_experimenter_mp_request_handle(struct channel *channel, struct pbuf *pbuf, struct ofp_header *xid_header) { lagopus_result_t ret = LAGOPUS_RESULT_ANY_FAILURES; struct pbuf_list *pbuf_list = NULL; struct ofp_experimenter_multipart_header exper_req; if (channel != NULL && pbuf != NULL && xid_header != NULL) { /* Parse packet. */ ret = ofp_experimenter_multipart_header_decode(pbuf, &exper_req); if (ret == LAGOPUS_RESULT_OK) { /* Experimenter request reply. */ ret = ofp_experimenter_mp_reply_create(channel, &pbuf_list, xid_header, &exper_req); if (ret == LAGOPUS_RESULT_OK) { ret = channel_send_packet_list(channel, pbuf_list); if (ret != LAGOPUS_RESULT_OK) { lagopus_msg_warning("Can't write.\n"); ret = LAGOPUS_RESULT_OFP_ERROR; } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); } } else { lagopus_msg_warning("FAILED (%s).\n", lagopus_error_get_string(ret)); ret = LAGOPUS_RESULT_OFP_ERROR; } /* free. */ if (pbuf_list != NULL) { pbuf_list_free(pbuf_list); } } else { ret = LAGOPUS_RESULT_INVALID_ARGS; } return ret; }
/* Desc Request packet receive. */ lagopus_result_t ofp_desc_request_handle(struct channel *channel, struct pbuf *pbuf, struct ofp_header *xid_header, struct ofp_error *error) { lagopus_result_t res = LAGOPUS_RESULT_ANY_FAILURES; uint64_t dpid; struct ofp_desc ofp_desc; struct pbuf_list *send_pbuf_list = NULL; /* check params */ if (channel != NULL && pbuf != NULL && xid_header != NULL && error != NULL) { dpid = channel_dpid_get(channel); /* get datas */ memset(&ofp_desc, 0, sizeof(ofp_desc)); res = ofp_desc_get(dpid, &ofp_desc, error); if (res == LAGOPUS_RESULT_OK) { /* create desc reply. */ res = ofp_desc_reply_create(channel, &send_pbuf_list, &ofp_desc, xid_header); if (res == LAGOPUS_RESULT_OK) { /* send desc reply */ res = channel_send_packet_list(channel, send_pbuf_list); if (res != LAGOPUS_RESULT_OK) { lagopus_msg_warning("Socket write error (%s).\n", lagopus_error_get_string(res)); } } else { lagopus_msg_warning("reply creation failed, (%s).\n", lagopus_error_get_string(res)); } pbuf_list_free(send_pbuf_list); } } else { res = LAGOPUS_RESULT_INVALID_ARGS; } return res; }
/* 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; }