void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to) { int ret; struct sockaddr_in addr; int net_socket; if ( to.type == NA_LOOPBACK ) { NET_SendLoopPacket (sock, length, data, to); return; } if (to.type == NA_BROADCAST) { net_socket = ip_sockets[sock]; if (!net_socket) return; } else if (to.type == NA_IP) { net_socket = ip_sockets[sock]; if (!net_socket) return; } else if (to.type == NA_IPX) { net_socket = ipx_sockets[sock]; if (!net_socket) return; } else if (to.type == NA_BROADCAST_IPX) { net_socket = ipx_sockets[sock]; if (!net_socket) return; } else Com_Error (ERR_FATAL, "NET_SendPacket: bad address type"); NetadrToSockadr (&to, &addr); // >>> FIX: For Nintendo Wii using devkitPPC / libogc // Switching to the equivalent function in the platform: //ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) ); //if (ret == -1) ret = net_sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, 8); if (ret < 0) // <<< FIX { Com_Printf ("NET_SendPacket ERROR: %s to %s\n", NET_ErrorString(), NET_AdrToString (to)); } }
int net_sendto_many(merlin_node **ntable, uint num, merlin_event *pkt) { uint i; if (!ntable || !pkt || !num || !*ntable) return -1; for (i = 0; i < num; i++) { merlin_node *node = ntable[i]; net_sendto(node, pkt); } return 0; }
int32_t udp_reactor_callback( CReactor *pReactor, CSocket *pSocket, void *pUserData ) { char recvBuf[1024] = { 0x00, }; CNetAddr stPeerAddr; int32_t iRetCode = net_recvfrom( pSocket, recvBuf, sizeof(recvBuf), &stPeerAddr ); if ( iRetCode > 0 ) { char respbuf[1024 * 2] = { 0x00, }; log_print( recvBuf ); sprintf( respbuf, "%s:%d hi, %s", stPeerAddr.pIP, stPeerAddr.iPort, recvBuf ); log_print( respbuf ); iRetCode = net_sendto( pSocket, respbuf, strlen(respbuf) + 1, &stPeerAddr ); if ( SOCKET_ERROR == iRetCode ) { perror( "send response msg failed:" ); log_print( "close socket, pSocket->iSocketId-->%d....................", pSocket->iSocketId ); remove_reactor_socket( pReactor, pSocket ); pSocket = NULL; } else log_print( "send udp response ok................" ); } else { log_print( "recv from failed?????????????????" ); if ( SOCKET_ERROR == iRetCode ) { log_print( "close socket, pSocket->iSocketId-->%d....................", pSocket->iSocketId ); remove_reactor_socket( pReactor, pSocket ); pSocket = NULL; } } return 0; }
int main( int argc, char **argv ) { int32_t iRetCode = -1; CReactor *iUDPReactorId = NULL; int8_t pLocalIP[32] = "225.0.0.37"; CThread *acceptTid = NULL; enable_log( 1 ); set_log( LOG_TYPE_CONSOLE, NULL, 0 ); if ( strlen( pLocalIP ) <= 0 ) if ( net_get_local_ip( pLocalIP, sizeof( pLocalIP ) ) < 0 ) return iRetCode; log_print( "%s %s:%d local ip-->%s\r\n", __FILE__, __FUNCTION__, __LINE__, pLocalIP ); if ( init_pine_system( ) < 0 ) return iRetCode; iUDPReactorId = net_reactor( ); if ( iUDPReactorId ) { if ( register_reactor_callback( iUDPReactorId, udp_reactor_callback, NULL ) < 0 ) { log_print( "%s %s:%d register reactor callback failed???????????\r\n", __FILE__, __FUNCTION__, __LINE__ ); return iRetCode; } iUDPClientSocketId = net_socket( SOCKET_TYPE_DGRAM, 0 ); if ( iUDPClientSocketId ) { CNetAddr addr, stLocalAddr; char tempBuf[1024] = { 0x00, }; int32_t iLen = 0; memset( &addr, 0x00, sizeof(addr) ); memset( &stLocalAddr, 0x00, sizeof(stLocalAddr) ); memcpy( addr.pIP, pLocalIP, strlen(pLocalIP) ); addr.iPort = LOCAL_PORT; memcpy( stLocalAddr.pIP, pLocalIP, strlen(pLocalIP) ); stLocalAddr.iPort = LOCAL_PORT + 1; if ( net_bind( iUDPClientSocketId, &stLocalAddr ) < 0 ) { log_print( "%s %s:%d socket bind failed???????????\r\n", __FILE__, __FUNCTION__, __LINE__ ); return iRetCode; } else log_print( "bind ok.............." ); if ( net_connect( iUDPClientSocketId, &addr ) < 0 ) { log_print( "%s %s:%d socket connect failed???????????\r\n", __FILE__, __FUNCTION__, __LINE__ ); return iRetCode; } else log_print( "connect ok.............." ); if ( add_reactor_socket( iUDPReactorId, iUDPClientSocketId, NULL ) < 0 ) { log_print( "%s %s:%d set add reactor socket failed???????????\r\n", __FILE__, __FUNCTION__, __LINE__ ); return iRetCode; } else log_print( "add reactor socket ok................." ); if ( net_set_socket( iUDPClientSocketId, SOCKET_OPTION_NONE_BLOCK, NULL, 0 ) < 0 ) { log_print( "%s %s:%d set socket none block failed???????????\r\n", __FILE__, __FUNCTION__, __LINE__ ); return iRetCode; } else log_print( "set socket none blocking ok....................." ); log_print( "multicast client is running.............." ); while ( fgets(tempBuf, sizeof(tempBuf), stdin) ) { int32_t iOpRet = net_sendto( iUDPClientSocketId, tempBuf, strlen(tempBuf) + 1, &addr ); log_print( "udp client: iOpRet->%d", iOpRet ); } } } while ( 1 ) os_sleep( 1000 ); net_close_reactor( iUDPReactorId ); return 0; }
int mcast_user_write(int fd, void *buf, int len, struct mcast_data *pri) { struct sockaddr_in *data_addr = pri->mcast_addr; return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); }
int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) { struct sockaddr_un *data_addr = pri->data_addr; return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr))); }
static int send_generic(merlin_event *pkt, void *data) { int result = 0; uint i, ntable_stop = num_masters + num_peers; linked_item *li; if ((!num_nodes || pkt->hdr.code == MAGIC_NONET) && !daemon_wants(pkt->hdr.type)) { ldebug("ipcfilter: Not sending %s event. %s, and daemon doesn't want it", callback_name(pkt->hdr.type), pkt->hdr.code == MAGIC_NONET ? "No-net magic" : "No nodes"); return 0; } if (!pkt->hdr.code == MAGIC_NONET && !daemon_wants(pkt->hdr.type)) { ldebug("ipcfilter: Not sending %s event. No-net magic and daemon doesn't want it", callback_name(pkt->hdr.type)); return 0; } pkt->hdr.len = merlin_encode_event(pkt, data); if (!pkt->hdr.len) { lerr("Header len is 0 for callback %d. Update offset in hookinfo.h", pkt->hdr.type); return -1; } if (is_dupe(pkt)) { ldebug("ipcfilter: Not sending %s event: Duplicate packet", callback_name(pkt->hdr.type)); return 0; } if (daemon_wants(pkt->hdr.type)) { result = ipc_send_event(pkt); /* * preserve the event so we can check for dupes, * but only if we successfully sent it */ if (result < 0) memset(&last_pkt, 0, sizeof(last_pkt)); else memcpy(&last_pkt, pkt, packet_size(pkt)); } if (!num_nodes) return 0; if (pkt->hdr.code == MAGIC_NONET) return 0; /* * The module can mark certain packets with a magic destination. * Such packets avoid all other inspection and get sent to where * the module wants us to. */ if (magic_destination(pkt)) { if ((pkt->hdr.selection & DEST_MASTERS) == DEST_MASTERS) { for (i = 0; i < num_masters; i++) { net_sendto(node_table[i], pkt); } } if ((pkt->hdr.selection & DEST_PEERS) == DEST_PEERS) { for (i = 0; i < num_peers; i++) { net_sendto(peer_table[i], pkt); } } if ((pkt->hdr.selection & DEST_POLLERS) == DEST_POLLERS) { for (i = 0; i < num_pollers; i++) { net_sendto(poller_table[i], pkt); } } return 0; } /* * "normal" packets get sent to all peers and masters, and possibly * a group of, or all, pollers as well */ /* general control packets are for everyone */ if (pkt->hdr.selection == CTRL_GENERIC && pkt->hdr.type == CTRL_PACKET) { ntable_stop = num_nodes; } /* Send this to all who should have it */ for (i = 0; i < ntable_stop; i++) { net_sendto(node_table[i], pkt); } /* if we've already sent to everyone we return early */ if (ntable_stop == num_nodes || !num_pollers) return 0; li = nodes_by_sel_id(pkt->hdr.selection); if (!li) { lerr("No matching selection for id %d", pkt->hdr.selection); return -1; } for (; li; li = li->next_item) { net_sendto((merlin_node *)li->item, pkt); } return result; }
/* * Sends an event read from the ipc socket to the appropriate nodes */ int net_send_ipc_data(merlin_event *pkt) { uint i, ntable_stop = num_masters + num_peers; linked_item *li; if (!num_nodes) return 0; /* * The module can mark certain packets with a magic destination. * Such packets avoid all other inspection and get sent to where * the module wants us to. */ if (magic_destination(pkt)) { if ((pkt->hdr.selection & DEST_MASTERS) == DEST_MASTERS) { for (i = 0; i < num_masters; i++) { net_sendto(node_table[i], pkt); } } if ((pkt->hdr.selection & DEST_PEERS) == DEST_PEERS) { for (i = 0; i < num_peers; i++) { net_sendto(peer_table[i], pkt); } } if ((pkt->hdr.selection & DEST_POLLERS) == DEST_POLLERS) { for (i = 0; i < num_pollers; i++) { net_sendto(poller_table[i], pkt); } } return 0; } /* * "normal" packets get sent to all peers and masters, and possibly * a group of, or all, pollers as well */ /* general control packets are for everyone */ if (pkt->hdr.selection == CTRL_GENERIC && pkt->hdr.type == CTRL_PACKET) { ntable_stop = num_nodes; } /* Send this to all who should have it */ for (i = 0; i < ntable_stop; i++) { net_sendto(node_table[i], pkt); } /* if we've already sent to everyone we return early */ if (ntable_stop == num_nodes || !num_pollers) return 0; li = nodes_by_sel_id(pkt->hdr.selection); if (!li) { lerr("No matching selection for id %d", pkt->hdr.selection); return -1; } for (; li; li = li->next_item) { net_sendto((merlin_node *)li->item, pkt); } return 0; }
/* * Passes an event from a remote node to the broker module, * any and all nocs and the database handling routines. The * exception to this rule is control packets from peers and * pollers, which never get forwarded to our masters. */ static int handle_network_event(merlin_node *node, merlin_event *pkt) { uint i; if (pkt->hdr.type == CTRL_PACKET) { /* * if this is a CTRL_ALIVE packet from a remote module, we * must take care to stash the start-time here so we can * forward it to our module later. It only matters for * peers, but we might as well set it for all modules */ if (pkt->hdr.code == CTRL_ACTIVE) { int result = handle_ctrl_active(node, pkt); /* * If the CTRL_ACTIVE packet shows compatibility * problems, we ignore it and move on */ if (result < 0) { return 0; } /* * If the info is new, we run the confsync check * for the recently activated node */ if (!result) { ldebug("Module @ %s is ACTIVE", node->name); csync_node_active(node); } } if (pkt->hdr.code == CTRL_INACTIVE) { memset(&node->info, 0, sizeof(node->info)); ldebug("Module @ %s is INACTIVE", node->name); db_mark_node_inactive(node); } } else if (node->type == MODE_POLLER && num_masters) { ldebug("Passing on event from poller %s to %d masters", node->name, num_masters); net_sendto_many(noc_table, num_masters, pkt); } else if (node->type == MODE_MASTER && num_pollers) { /* * @todo maybe we should also check if self.peer_id == 0 * before we forward events to our pollers. Hmm... */ if (pkt->hdr.type != NEBCALLBACK_PROGRAM_STATUS_DATA && pkt->hdr.type != NEBCALLBACK_CONTACT_NOTIFICATION_METHOD_DATA) { for (i = 0; i < num_pollers; i++) { merlin_node *node = poller_table[i]; net_sendto(node, pkt); } } } /* * let the various handler know which node sent the packet */ pkt->hdr.selection = node->id; /* not all packets get delivered to the merlin module */ switch (pkt->hdr.type) { case NEBCALLBACK_PROGRAM_STATUS_DATA: case NEBCALLBACK_CONTACT_NOTIFICATION_METHOD_DATA: /* * PROGRAM_STATUS_DATA can't sanely be transferred * CONTACT_NOTIFICATION_METHOD is left as-is, since we by * default want pollers to send notifications for their * respective contacts. This is by customer request, since * sending text-messages across country borders is a lot * more expensive than just buying a GSM device extra for * where one wants to place the poller */ mrm_db_update(node, pkt); return 0; /* and not all packets get sent to the database */ case CTRL_PACKET: case NEBCALLBACK_EXTERNAL_COMMAND_DATA: return ipc_send_event(pkt); case NEBCALLBACK_DOWNTIME_DATA: case NEBCALLBACK_COMMENT_DATA: /* * These two used to be handled specially here, but * we've moved it to the database update layer instead, * which will discard queries it can't run properly * without bouncing the data against the module. */ default: /* * IMPORTANT NOTE: * It's absolutely vital that we send the event to the * ipc socket *before* we ship it off to the db_update * function, since the db_update function merlin_decode()'s * the event, which makes unusable for sending to the * ipc (or, indeed, anywhere else) afterwards. */ ipc_send_event(pkt); mrm_db_update(node, pkt); return 0; } return 0; }