static gboolean listener_event(GIOChannel *channel, GIOCondition condition, gpointer user_data) { GDHCPServer *dhcp_server = user_data; struct dhcp_packet packet; struct dhcp_lease *lease; uint32_t requested_nip = 0; uint8_t type, *server_id_option, *request_ip_option; int re; if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) { dhcp_server->listener_watch = 0; return FALSE; } re = dhcp_recv_l3_packet(&packet, dhcp_server->listener_sockfd); if (re < 0) return TRUE; type = check_packet_type(&packet); if (type == 0) return TRUE; server_id_option = dhcp_get_option(&packet, DHCP_SERVER_ID); if (server_id_option) { uint32_t server_nid = dhcp_get_unaligned( (uint32_t *) server_id_option); if (server_nid != dhcp_server->server_nip) return TRUE; } request_ip_option = dhcp_get_option(&packet, DHCP_REQUESTED_IP); if (request_ip_option) requested_nip = dhcp_get_unaligned( (uint32_t *) request_ip_option); lease = find_lease_by_mac(dhcp_server, packet.chaddr); switch (type) { case DHCPDISCOVER: debug(dhcp_server, "Received DISCOVER"); send_offer(dhcp_server, &packet, lease, requested_nip); break; case DHCPREQUEST: debug(dhcp_server, "Received REQUEST NIP %d", requested_nip); if (requested_nip == 0) { requested_nip = packet.ciaddr; if (requested_nip == 0) break; } if (lease && requested_nip == lease->lease_nip) { debug(dhcp_server, "Sending ACK"); send_ACK(dhcp_server, &packet, lease->lease_nip); break; } if (server_id_option || lease == NULL) { debug(dhcp_server, "Sending NAK"); send_NAK(dhcp_server, &packet); } break; case DHCPDECLINE: debug(dhcp_server, "Received DECLINE"); if (server_id_option == NULL) break; if (request_ip_option == NULL) break; if (lease == NULL) break; if (requested_nip == lease->lease_nip) remove_lease(dhcp_server, lease); break; case DHCPRELEASE: debug(dhcp_server, "Received RELEASE"); if (server_id_option == NULL) break; if (lease == NULL) break; if (packet.ciaddr == lease->lease_nip) lease_set_expire(dhcp_server, lease, time(NULL)); break; case DHCPINFORM: debug(dhcp_server, "Received INFORM"); send_inform(dhcp_server, &packet); break; } return TRUE; }
static gboolean listener_event(GIOChannel *channel, GIOCondition condition, gpointer user_data) { GDHCPServer *dhcp_server = user_data; struct dhcp_packet packet; struct dhcp_lease *lease; uint32_t requested_nip = 0; uint8_t type, *server_id_option, *request_ip_option, *host_name; int re; GDHCPOptionType option_type; char *option_value; if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) { dhcp_server->listener_watch = 0; return FALSE; } re = dhcp_recv_l3_packet(&packet, dhcp_server->listener_sockfd); if (re < 0) return TRUE; type = check_packet_type(&packet); if (type == 0) return TRUE; server_id_option = dhcp_get_option(&packet, DHCP_SERVER_ID); if (server_id_option) { uint32_t server_nid = get_be32(server_id_option); if (server_nid != dhcp_server->server_nip) return TRUE; } request_ip_option = dhcp_get_option(&packet, DHCP_REQUESTED_IP); if (request_ip_option) requested_nip = get_be32(request_ip_option); lease = find_lease_by_mac(dhcp_server, packet.chaddr); switch (type) { case DHCPDISCOVER: debug(dhcp_server, "Received DISCOVER"); send_offer(dhcp_server, &packet, lease, requested_nip); break; case DHCPREQUEST: debug(dhcp_server, "Received REQUEST NIP %d", requested_nip); if (requested_nip == 0) { requested_nip = packet.ciaddr; if (requested_nip == 0) break; } if (lease && requested_nip == lease->lease_nip) { debug(dhcp_server, "Sending ACK"); host_name = dhcp_get_option(&packet, DHCP_HOST_NAME); option_type = dhcp_get_code_type(DHCP_HOST_NAME); option_value = malloc_option_value_string(host_name, option_type); send_ACK(dhcp_server, &packet, lease->lease_nip); if (dhcp_server->save_ack_lease_func) dhcp_server->save_ack_lease_func( option_value, lease->lease_mac, lease->lease_nip); g_free(option_value); break; } if (server_id_option || !lease) { debug(dhcp_server, "Sending NAK"); send_NAK(dhcp_server, &packet); } break; case DHCPDECLINE: debug(dhcp_server, "Received DECLINE"); if (!server_id_option) break; if (!request_ip_option) break; if (!lease) break; if (requested_nip == lease->lease_nip) remove_lease(dhcp_server, lease); break; case DHCPRELEASE: debug(dhcp_server, "Received RELEASE"); if (!server_id_option) break; if (!lease) break; if (packet.ciaddr == lease->lease_nip) lease_set_expire(dhcp_server, lease, time(NULL)); break; case DHCPINFORM: debug(dhcp_server, "Received INFORM"); send_inform(dhcp_server, &packet); break; } return TRUE; }
void tskHandleRequests(void *pvParameters) { packet_t *requestPacket = NULL; packet_t *responsePacket = NULL; json_t *idObj; json_int_t id; char *errorString; strbuffer_t *errorBuffer; strbuffer_t *logMsg; portBASE_TYPE xStatus; while(1) { if(uxQueueMessagesWaiting(requestQueue) > 0) { xStatus = xQueueReceive( requestQueue, &requestPacket, (portTickType) QUEUE_RECEIVE_WAIT_TIMEOUT ); if( (xStatus == pdPASS) && requestPacket) { if(check_packet_type(requestPacket, PKG_TYPE_INCOME_JSONRPC_REQUEST) != TRUE) { logger(LEVEL_ERR, "Wrong data packet from requestQueue. Deleting packet" ); packet_destroy(&requestPacket); continue; } logMsg = strbuffer_new(); strbuffer_append(logMsg, "Received new request: id="); strbuffer_append(logMsg, int_to_string(requestPacket->id)); strbuffer_append(logMsg, " transport="); strbuffer_append(logMsg, int_to_string(requestPacket->transport)); logger(LEVEL_INFO, logMsg->value); strbuffer_destroy(&logMsg); handle_request(requestPacket); responsePacket = requestPacket; if(responsePacket) { if(requestPacket->type == PKG_TYPE_OUTCOME_JSONRPC_NOTIFICATION) { logger(LEVEL_INFO, "Request was notification only. Destroying response"); packet_destroy(&requestPacket); packet_destroy(&responsePacket); continue; } if(check_packet_type(requestPacket, PKG_TYPE_OUTCOME_JSONRPC_RESPONSE) != TRUE) { logger(LEVEL_ERR, "Wrong response packet. Deleting packet" ); packet_destroy(&requestPacket); continue; } logMsg = strbuffer_new(); strbuffer_append(logMsg, "Received response: id="); strbuffer_append(logMsg, int_to_string(responsePacket->id)); strbuffer_append(logMsg, " transport="); strbuffer_append(logMsg, int_to_string(responsePacket->transport)); logger(LEVEL_INFO, logMsg->value); strbuffer_destroy(&logMsg); logger(LEVEL_DEBUG, "creating json string from json object"); strbuffer_t *stringData = strbuffer_new(); char *jsonData = json_dumps(responsePacket->payload.jsonDoc, JSON_ENCODE_ANY ); if(jsonData) { logger(LEVEL_DEBUG, "json string was created. Creating packet to send."); strbuffer_append(stringData, jsonData); logMsg = strbuffer_new(); strbuffer_append(logMsg, "Sending new packet: packet_length="); strbuffer_append(logMsg, int_to_string(stringData->length)); strbuffer_append(logMsg, " packet_transport="); strbuffer_append(logMsg, int_to_string(responsePacket->transport)); logger(LEVEL_DEBUG, logMsg->value); strbuffer_destroy(&logMsg); } else { logMsg = strbuffer_new(); strbuffer_append(logMsg, "Unable to create string from response json: id="); strbuffer_append(logMsg, int_to_string(responsePacket->id)); strbuffer_append(logMsg, " transport="); strbuffer_append(logMsg, int_to_string(responsePacket->transport)); logger(LEVEL_WARN, logMsg->value); strbuffer_destroy(&logMsg); errorString = format_jsonrpc_error(JSONRPC_SERVER_ERROR, MSG_JSONRPC_ERRORS.server_error, "internal server error", responsePacket->id); strbuffer_append(stringData, errorString); } vPortFree(jsonData); packet_lock(responsePacket); { json_decref(responsePacket->payload.jsonDoc); responsePacket->type = PKG_TYPE_OUTGOING_MESSAGE_STRING; responsePacket->payload.stringData = stringData; } packet_unlock(responsePacket); sendOutputMessage(responsePacket); // idObj = json_object_get(responseJson, "id"); // id = json_integer_value(idObj); // // json_t *transportObject = json_object_get(responseJson, "transport"); // json_int_t transport = json_integer_value(transportObject); // // logger_format(LEVEL_INFO, "Received response. id = %d transport=%s", (int) id, transport_type_to_str((transport_type_t) transport)); // // xStatus = xQueueSendToBack( responseQueue, &responseJson, (portTickType) QUEUE_SEND_WAIT_TIMEOUT ); // if( xStatus != pdPASS ){ // char* idStr = json_dumps(json_object_get(requestPacket, "id"), JSON_ENCODE_ANY); // json_int_t transport = json_integer_value(json_object_get(requestPacket, "transport")); // json_object_del(requestPacket, "transport"); // json_decref(requestJson); // // send using error reporting function // if(id && transport) { // report_error_to_sender( // (transport_type_t) transport, // MSG_JSONRPC_ERRORS.general_error_json, // JSONRPC_SERVER_ERROR, /* <-- code */ // MSG_JSONRPC_ERRORS.server_error, /* <-- message */ // MSG_MAINTASKS.tskAbstractReader.device_is_busy_timeout , /* <-- data */ // idStr // ); // } // if(idStr) vPortFree(idStr); // logger_format(LEVEL_INFO, "Unable to add response to queue. Request id = %d", (int) id ); // } else { // logger(LEVEL_DEBUG, "Response was added to response queue"); // } } // json_decref(requestPacket); } } taskYIELD(); } }