udpsend.h:

/****************************************************************************************
 * udpsend.h v1.0 by Kareem Abu-Zahra (kareem_net@hotmail.com)
 *
 * Contains definitions and function protoypes for udpsend.c. Udpsend is meant
 * to be used as a client to any number of udp servers (services). It will
 * also wait for an ACK from the server to insure the server is actually up. 
 *
 *
 *	Function: udpinit(uctx *ctx, SERVICE)
 *
 *  Description: Initializes a context with a SERVICE that is defined
 *  			 in the services.h file.
 *
 *  Returns: 0 on Success, a negative number on Error.
 *
 *
 *
 *	Function: udpsend(uctx *ctx, char *msg)
 *
 *  Description: Sends a message to the service defined by the ctx.
 *
 *  Returns: A negative number on Error or Server Timeout
 *  		 On success, returns the number of characters transmitted.
 *
 *	Function: udpclose(uctx *ctx)
 *
 *  Description: Closes a context (closes the socket). 
 *
 *  Returns: 0 on Success
 *
 *
 * Example:
 *
 * 	uctx ctx;
 * 
 * 	udpinit(&ctx, PROLITE);
 * 
 * 	udpsend(&ctx, "message1");
 * 	.
 * 	.
 *	.
 * 	udpsend(&ctx, "message2");
 * 
 * 	udpclose(&ctx);
 *
 */	

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>

#include "services.h"

#ifndef __UDPSEND_H
#define __UDPSEND_H

#define SERV_HOST_ADDR	"127.0.0.1"


#define getport(service)	\
	service ## _PORT

#define getlimit(service)	\
	service ## _LIMIT


/* ERROR DEFINITIONS */
#define ERROR_SERVER_SOCKET	-1;
#define ERROR_CTX_CLOSED	-2;
#define ERROR_SEND			-3;
#define ERROR_NO_ACK		-4;
#define ERROR_BAD_ACK		-5;
#define ERROR_SELECT		-6;


/* CTX STATES */
#define CTX_OPEN	0xdeadbeef
#define CTX_CLOSED	0x00000000


typedef struct {
	int port;
	int send_max;
	int serv_sock;		
	unsigned int state;	
	struct sockaddr_in serv_addr;
} uctx; 

//typedef struct uctx	uctx;


#define min(a, b)	(((a)<(b))?(a):(b)) 

#define udpinit(ctx, service) \
	kudpinit(ctx, service ## _PORT, service ## _LIMIT);

#ifdef __cplusplus
extern "C" {
#endif

int kudpinit(uctx *ctx, int port, int send_max);
int udpsend(uctx *ctx, char *msg);
int udpclose(uctx *ctx);


#ifdef __cplusplus
}
#endif
#endif

udpsend.c:

//#include <fcntl.h>   /* File control definitions */
//#include <errno.h>   /* Error number definitions */
//#include <termios.h> /* POSIX terminal control definitions */

#include "udpsend.h"
#include <unistd.h>
#include <strings.h>
#include <string.h>
//#include <sys/socket.h>
       #include <sys/socket.h>
       #include <netinet/in.h>
       #include <arpa/inet.h>


int kudpinit(uctx *ctx, int port, int send_max)
{
	int len;

	ctx->port = port;
	ctx->send_max = send_max;

	/* Open port to server */

	bzero((char *) &ctx->serv_addr, sizeof(ctx->serv_addr));
	ctx->serv_addr.sin_family = AF_INET;
	ctx->serv_addr.sin_addr.s_addr = inet_addr(SERV_HOST_ADDR);
	ctx->serv_addr.sin_port = htons(ctx->port);

	if ((ctx->serv_sock = socket(AF_INET, SOCK_DGRAM, 0)) <0) {
		return ERROR_SERVER_SOCKET;
	}

	ctx->state = CTX_OPEN;

	return 0;
}

int udpsend(uctx *ctx, char *msg)
{
	int r;
	char c;
	fd_set fds;
	struct timeval tv;

	int len;
	printf("in udpsend to send %s\n", msg);
	if (ctx->state != CTX_OPEN)
		return ERROR_CTX_CLOSED;

	if ((r = sendto(ctx->serv_sock, msg, min(ctx->send_max, strlen(msg)), 0, (struct sockaddr *)&ctx->serv_addr, sizeof(ctx->serv_addr))) < 0)
		return ERROR_SEND;


	//wait for ack, we are already bound on our port

	FD_ZERO(&fds);
	FD_SET(ctx->serv_sock, &fds);
	tv.tv_sec = 1;
	//	tv.tv_usec = 300000;
	tv.tv_usec = 0;
	r = select(ctx->serv_sock + 1, &fds, NULL, NULL, &tv);

	printf("select returned: %d\n", r);

	if (r == -1)
	{
		return ERROR_SELECT;
	} else {
		if (r) {
			if (r = recvfrom(ctx->serv_sock, (char *)&c, 1, 0, NULL, NULL) < 1)
				return r;       //r could be 0 (shutdown from peer) or -1 (error)

			if (c = 0x01)
				return 0;
			else
				return ERROR_BAD_ACK;
		} else {
			return ERROR_NO_ACK;
		}

	}

}

int udpclose(uctx *ctx)
{
	close(ctx->serv_sock);

	ctx->state = CTX_CLOSED;

	return 0;
}

services.h:

/****************************************************************************************
 * services.h v1.0 by Kareem Abu-Zahra (kareem_net@hotmail.com)
 *
 * This file is included by the server and client code. A service is 
 * defined by a port and the maximum amount of characters it can 
 * handle. Example:
 *
 * #define PROLITE_PORT         9000
 * #define PROLITE_LIMIT        490
 */

#ifndef __SERVICES_H
#define __SERVICES_H


/* PORT DEFINITIONS */
#define PROLITE_PORT    9000
#define STEERING_PORT   9001

/* SEND_MAX DEFINITIONS */
#define PROLITE_LIMIT   490
#define STEERING_LIMIT  490

#endif