📄 ms_udp.c
字号:
/* * * Copyright (c) Sigma Designs, Inc. 2005. All rights reserved. * */#define ALLOW_OS_CODE 1#include "rmdef/rmdef.h"#include "rmcore/include/rmascii.h"#include <stdio.h>#include "ms_udp.h"#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <string.h>#include <errno.h>#include <netdb.h>#include <time.h>#include <sys/poll.h>#define MAX_BUFFER_SIZE 1024static RMuint8 udp_buffer[MAX_BUFFER_SIZE];struct ms_udp_socket_s { int sockfd; struct sockaddr_in name;};/** * Create a new UDP socket, connected to address *address by default * * @param address - IP address of the MS server * @return a valid ms_udp_socket_t, or NULL on error */ms_udp_socket_t * open_ms_udp_socket(RMascii *address){ ms_udp_socket_t *ms_socket = NULL; RMascii *paddress = NULL; RMuint16 port; RMascii *host; RMascii *port_string; struct hostent *hostinfo; int status; ms_socket = (ms_udp_socket_t *)RMMalloc(sizeof(ms_udp_socket_t)); if (ms_socket == NULL) return NULL; ms_socket->sockfd = socket(PF_INET, SOCK_DGRAM, 0); if (ms_socket->sockfd < 0){ RMDBGLOG((ENABLE,"Error creating socket : %s\n", strerror(errno))); goto error; } paddress = RMMallocAndDuplicateAscii(address); if (paddress == NULL) goto error; if (RMFindAsciiCharacter(paddress, ':', &host)) host++; else goto error; if (RMFindAsciiCharacter(host, ':', &port_string)){ port_string[0] = 0; port_string++; RMasciiToUInt16(port_string, &port); port = htons(port); } else goto error; ms_socket->name.sin_family = AF_INET; ms_socket->name.sin_port = port; hostinfo = gethostbyname (host); if (hostinfo == NULL) { RMDBGLOG((ENABLE, "Error getting host address for %s : %s\n", host, strerror(errno))); goto error; } ms_socket->name.sin_addr = *(struct in_addr *) hostinfo->h_addr; status = connect(ms_socket->sockfd, (struct sockaddr *)&(ms_socket->name), sizeof(ms_socket->name)); if (status < 0){ RMDBGLOG((ENABLE, "Error connecting the socket : %s\n", strerror(errno))); goto error; } RMFree(paddress); return ms_socket;error : if (ms_socket) RMFree(ms_socket); if (paddress) RMFree(paddress); return NULL;} /** * Close a UDP connection, and free associated resources * * @param ms_socket - the socket to close */void close_ms_udp_socket(ms_udp_socket_t *ms_socket){ int status; if (ms_socket == NULL) return; status = shutdown(ms_socket->sockfd, SHUT_RDWR); if (status < 0) RMDBGLOG((ENABLE,"Error closing MS socket : %s\n", strerror(errno))); RMFree(ms_socket);} /** * Send a UDP packet and wait for the anser for a given time. This function is * not reentrant, the answer should not be freed and a subsequent call to * ms_udp_send_receive will modify it. * * @param ms_socket - ms_socket to use * @param message * @param message_size * @param answer - answer received * @param answer_size - size of the answer * @param small_dealy_ms - delay between attempts (ms) * @param big_delay_s - global delay (s) * @return RM_OK on success, RM_ERROR if no message received in the given delay */RMstatus ms_udp_send_receive(ms_udp_socket_t *ms_socket, RMuint8 *message, RMuint32 message_size, RMuint8 **answer, RMuint32 *answer_size, RMuint32 small_dealy_ms, RMuint32 big_delay_s){ ssize_t sent_bytes; time_t end_time; RMuint32 attempt = 0; struct pollfd mpoll; int status; if (ms_socket == NULL || message == NULL || message_size == 0) return RM_ERROR; end_time = time(NULL) + (time_t) big_delay_s; while (end_time > time(NULL)){ /* Try sending the message again */ RMDBGLOG((ENABLE,"Send %ld bytes message, attempt %ld\n", message_size, attempt)); sent_bytes = send(ms_socket->sockfd, (void *)message, (size_t)message_size, 0); if (sent_bytes < 0 ){ RMDBGLOG((ENABLE,"Error sending UDP message : %s\n", strerror(errno))); goto error; } else if ((unsigned) sent_bytes != message_size) { RMDBGLOG((ENABLE,"Error, only %ld/%ld bytes sent\n", sent_bytes, message_size)); goto error; } /* Wait for answer */ mpoll.fd = ms_socket->sockfd; mpoll.events = POLLIN | POLLPRI; status = poll(&mpoll, 1, (int) small_dealy_ms); if (status < 0 ){ RMDBGLOG((ENABLE,"Error polling socket : %s\n", strerror(errno))); goto error; } else if ( status == 0 ) { RMDBGLOG((ENABLE,"Poll timed out ...\n")); attempt++; continue; } /* Something happened in time */ if (mpoll.revents & (POLLIN|POLLPRI)){ int nread; nread = recv(ms_socket->sockfd, udp_buffer, MAX_BUFFER_SIZE, MSG_DONTWAIT); if (nread < 0){ RMDBGLOG((ENABLE,"Error reading MS socket : %s\n", strerror(errno))); goto error; } else if (nread == MAX_BUFFER_SIZE) { RMDBGLOG((ENABLE, "Error, too many data received\n")); goto error; } RMDBGLOG((ENABLE,"Received %ld bytes from MS server\n", nread)); *answer = udp_buffer; *answer_size = nread; return RM_OK; } else { RMDBGLOG((ENABLE,"Errorm, unexpected event happened\n")); goto error; } } RMDBGLOG((ENABLE,"Global timeout of %ld seconds reached, abort\n", big_delay_s));error: return RM_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -