Skip to content

Instantly share code, notes, and snippets.

@s9gf4ult
Created July 19, 2013 09:50
Show Gist options
  • Save s9gf4ult/6038024 to your computer and use it in GitHub Desktop.
Save s9gf4ult/6038024 to your computer and use it in GitHub Desktop.
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <readline/history.h>
#define BUFSIZE 1000
int sendMsg(int const sock, struct sockaddr const *addr) {
int ret = 0;
char *msg;
if (! (msg = readline("enter message: "))) {
printf("could not read message\n");
ret = 1;
goto freemsg;
}
if (-1 == sendto(sock,
msg,
strlen(msg),
0,
addr,
sizeof(struct sockaddr))) {
printf("error while sending message\n");
ret = 1;
goto freemsg;
}
printf("message sent\n");
freemsg:
free(msg);
return ret;
}
int recvMsg(int const sock) {
int ret = 0;
void *buf;
char *cbuf;
int msglen;
if (! (buf = malloc(BUFSIZE))) {
printf("could not allocate memory\n");
ret = 1;
goto end;
}
if (-1 == (msglen = recvfrom(sock,
buf,
BUFSIZE-1,
0,
0,
0))) {
printf("could not receive message, errno %d\n", errno);
ret = 1;
goto freebuf;
}
cbuf = (char*)buf;
cbuf[msglen] = 0;
printf("message is: %s\n", cbuf);
freebuf:
free(buf);
end:
return ret;
}
int getBindedSock(int * const outsock, struct sockaddr const *addr) {
int ret = 0;
int sock;
if(-1 == (sock = socket(AF_INET, SOCK_DGRAM, 0))) {
printf("can not open socket, errno %d\n", errno);
ret = 1;
goto end;
}
if (-1 == bind(sock, addr, sizeof(struct sockaddr))) {
printf("can not bind socket, errno %d\n", errno);
ret = 1;
close(sock);
goto end;
}
*outsock = sock;
end:
return ret;
}
int getsockaddr(char const *laddr, char const *lport, struct sockaddr *saddr) {
int ret = 0;
struct addrinfo hint, *ainfo;
memset(&hint, 0, sizeof(struct addrinfo));
hint.ai_family = AF_INET;
hint.ai_socktype = SOCK_DGRAM;
if (getaddrinfo(laddr, lport, &hint, &ainfo)) {
printf("could not get addrinfo, for address %s:%s, errno %d", laddr, lport, errno);
ret = -1;
} else {
memcpy((void*)saddr, ainfo->ai_addr, sizeof(struct sockaddr));
freeaddrinfo(ainfo);
}
return ret;
}
#define ERRJMP( labelname, ... ) \
{ \
printf( __VA_ARGS__ ); \
ret = -1; \
quit = 1; \
goto labelname; \
}
int run(struct sockaddr const *laddr, struct sockaddr const *saddr) {
int ret = 0;
int quit = 0;
int sock;
if (getBindedSock(&sock, laddr)) {
printf("could not get socket");
return -1;
}
while(!quit) {
char *cmd;
if (! (cmd = readline("s - send, l - listen, q - quit > ")))
ERRJMP( endwhile, "Could not read line, errno %d\n", errno );
if (! strcmp(cmd, "l")) { /* equal to "l" */
if (recvMsg(sock))
ERRJMP( freecmd, "could not receive message" );
} else if (! strcmp(cmd, "s")) {
if (sendMsg(sock, saddr))
ERRJMP( freecmd, "could not send message" );
} else if (! strcmp(cmd, "q")) {
printf("quitting\n");
quit = 1;
} else {
printf("dont understand \"%s\"\n", cmd);
}
freecmd:
free(cmd);
endwhile:;
}
close(sock);
return ret;
}
#undef ERRJMP
int main(int argc, char **argv) {
int ret = 0;
if ((argc-1) != 4) {
printf("call: {ADDRES} {PORT} {ADDRESS} {PORT}\n");
printf("where the first address and port is for listening and second is for sending messsages to.\n");
} else {
char *laddr, *lport, *saddr, *sport;
struct sockaddr listenAddr, sendAddr;
laddr = argv[1];
lport = argv[2];
saddr = argv[3];
sport = argv[4];
if (-1 != getsockaddr(laddr, lport, &listenAddr) &&
-1 != getsockaddr(saddr, sport, &sendAddr)) {
ret = run(&listenAddr, &sendAddr);
}
}
return ret;
}
CFLAGS := -pedantic -Wall -Wextra -std=gnu99
LDFLAGS := -lreadline
SOURCES := $(wildcard *.c)
TARGETS := $(patsubst %.c, %, $(SOURCES))
CLEANS := $(patsubst %.c, %_clean, $(SOURCES))
$(TARGETS): %: %.c
gcc -o $@ $(CFLAGS) $(LDFLAGS) $^
$(CLEANS):
rm $(patsubst %_clean, %, $@) || echo "removed"
all: $(TARGETS)
clean: $(CLEANS)
.PHONY: all clean $(CLEANS)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment