diff options
| -rw-r--r-- | src/aa_socket.cc | 256 | ||||
| -rw-r--r-- | src/aa_socket.h | 42 | 
2 files changed, 298 insertions, 0 deletions
| diff --git a/src/aa_socket.cc b/src/aa_socket.cc new file mode 100644 index 0000000..bd9328c --- /dev/null +++ b/src/aa_socket.cc @@ -0,0 +1,256 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +#include "aa_socket.h" + +#include <string.h> +#include <stdio.h> + +#include <iostream> +using namespace std; + +#include <unistd.h> +//#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <errno.h> + +#include <netinet/in.h> +#if defined(linux) +#include <endian.h> +#else +#include <sys/endian.h> +#endif /*defined(linux)*/ + +// for gethostbyname +#include <netdb.h> + +// These functions are wrappers, to preserve my nice method naming! +inline int _socket(int a,int b,int c){return socket(a,b,c);}  +inline int _connect(int a,const struct sockaddr *b,socklen_t c){return connect(a,b,c);} +inline int _listen(int a,int b){return listen(a,b);} +inline int _send(int a,char *b,unsigned int c, int d){return send(a,b,c,d);} + + +AASocket::AASocket() +{ +} + +AASocket::~AASocket() +{ +  int err = close(socket);  // close server +	if(err == -1) throw Network_error("close", strerror(errno)); +} + +void AASocket::connect(const char *host, unsigned short port) +{ +  // create socket +  socket = _socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);  +  // PF_INET: ipv4, PF_INET6: ipv6 +  // tcp: IPPROTO_TCP +  // upd: IPPROTO_UDP + +  if (socket == -1) throw Network_error("socket", strerror(errno)); + +  socketaddr.sin_family = AF_INET; // Use "internet protocol" IP +  socketaddr.sin_port = htons(port);  // connect to that port +  socketaddr.sin_addr.s_addr = INADDR_ANY; +  // INADDR_ANY puts your IP address automatically + + + +	struct hostent *hp = gethostbyname(host); +	//	memcpy(&socketaddr.sin_addr.s_addr, *(hp->h_addr_list),sizeof(struct in_addr)); +	memcpy(&(socketaddr.sin_addr),*(hp->h_addr_list),sizeof(struct in_addr)); + +	// FIXME: gethostbyname() +	//  socketaddr.sin_addr.s_addr = inet_addr(host);  +  //inet_aton (ip, &socketaddr.sin_addr); +   +  int err = _connect(socket, (struct sockaddr*)&socketaddr, sizeof(socketaddr)); +	if(err == -1) throw Network_error("connect", strerror(errno)); +} + +void AASocket::listen(unsigned short port) +{ +	int err; + +	bind_socket = _socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); +	if(bind_socket == -1) throw Network_error("tmp socket", strerror(errno)); +	 +	int optval = 1; +	err = setsockopt(bind_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); +	if(err == -1) throw Network_error("setsockopt", strerror(errno)); + +  socketaddr.sin_family = AF_INET; // Use "internet protocol" IP +  socketaddr.sin_port = htons(port);  // connect to that port +  socketaddr.sin_addr.s_addr = INADDR_ANY; +  // INADDR_ANY puts your IP address automatically +	 +	// bind socket to address specified by "sa" parameter +	err = bind(bind_socket, (struct sockaddr*)&socketaddr, sizeof(socketaddr)); +	if(err == -1) throw Network_error("bind", strerror(errno)); +	 +	err = _listen(bind_socket, 5); +	if(err == -1) throw Network_error("listen", strerror(errno)); + +  int csalen = sizeof(socketaddr); +  socket = accept(bind_socket,  +									(struct sockaddr*)&socketaddr,  +									(socklen_t*)&csalen); +	if(socket == -1) throw Network_error("accept", strerror(errno)); + +	err = close(bind_socket); // We don't need this anymore +  bind_socket = -1; +	if(err == -1) throw Network_error("tmp close", strerror(errno)); +} + + +void AASocket::force_close() +{ +  if(bind_socket != -1) close(bind_socket); // This should break the accept call +} + + +void AASocket::send(const char* buf, unsigned int size) +{ +	//unsigned int newsize = size + sizeof(unsigned int); +	//	char *newbuf = new char[newsize]; + +	unsigned int nsize = htonl(size); +	int n = _send(socket, (char*)&nsize, sizeof(unsigned int), MSG_WAITALL); +	if(n == -1) throw Network_error("send", strerror(errno)); + +	n = _send(socket, (char *)buf, size, MSG_WAITALL); +	if(n == -1) throw Network_error("send", strerror(errno)); +} + + +int AASocket::receive(char* buf, unsigned int size) +{ +	unsigned int insize; +	 +	int n = recv(socket, &insize, sizeof(unsigned int), MSG_WAITALL); +	if(n == -1) throw Network_error("recv", strerror(errno)); + +	insize = ntohl(insize); + +	if(insize > size) { +		char err_buf[256]; +		sprintf(err_buf, "Buffer is too small. Should be %d is %d." , insize, size); +		throw Network_error("receive", err_buf); +	} +	 +	n = recv(socket, buf, insize, MSG_WAITALL); +	if(n == -1) throw Network_error("recv", strerror(errno)); + +	return n; +} + + +void AASocket::send_string(string str) +{ +	this->send((char*)str.c_str(), str.length()); +} + + +string AASocket::receive_string() +{ +	char buf[1024]; +	memset(buf, 0, sizeof(buf)); + +	receive(buf, sizeof(buf)); + +  return string(buf); +} + + + +#ifdef TEST_SOCKET + +/** + * Test application for AASocket + * It should print the following to stdout: + * A: Hello, how are you? + * B: Fine thanks. + * A: What about you? + * B: I'm fine too. + */ + +#include <sys/types.h> +#include <unistd.h> + +#include <string> +#include <iostream> + +int main() +{ +	char buf[1024]; +	memset(buf, 0, sizeof(buf)); +  int f = fork(); +  switch(f) { +  case -1: // Fork error +    perror("Fork failed!"); +    return 1; + +  case 0:  // Forked child +		{ +			try { +				AASocket out; + +				sleep(1); // Make sure the other end is listening + +				// Test connect +				out.connect("127.0.0.1", 6666); + +				// Test raw communication send +				sprintf(buf, "Hello how are you?"); +				out.send(buf, sizeof(buf)); + +				// Test raw communication receive +				out.receive(buf, sizeof(buf)); +				std::cout << "B: " << buf << std::endl; + +				// Test string receive +				std::string q = out.receive_string(); +				std::cout << "B: " << q << std::endl; + +				// Test string send +				out.send_string(std::string("I'm fine too.")); +				return 0; +			} catch(Network_error e) { +				std::cerr << "Out: " << e.error << std::endl; +			} +		} +  default: // Parent +		{ +			try { +				AASocket in; +				 +				// Test listen +				in.listen(6666); + +				// Test raw communication receive +				in.receive(buf, sizeof(buf)); +				std::cout << "A: " << buf << std::endl; + +				// Test raw communication send +				sprintf(buf, "Fine thanks."); +				in.send(buf, sizeof(buf)); + +				// Test string send +				in.send_string(std::string("What about you?")); + +				// Test string receive	 +				std::string a = in.receive_string(); +				std::cout << "A: " << a << std::endl; +				return 0; +			} catch(Network_error e) { +				std::cerr << "In: " << e.error << std::endl; +			} +		} +	} +	return 0; +} +#endif/*TEST_SOCKET*/ diff --git a/src/aa_socket.h b/src/aa_socket.h new file mode 100644 index 0000000..8b077f3 --- /dev/null +++ b/src/aa_socket.h @@ -0,0 +1,42 @@ +#ifndef __SOCKET_H__ +#define __SOCKET_H__ + +#include <string> + +#include <netinet/in.h> +//#include <sys/socket.h> + + +/** + * Exceptions + */ +struct Network_error { +	Network_error(const char *event, const char *err) { +		error = std::string(err) + " - in " + std::string(event); +	} +	std::string error; +}; + +class AASocket { +public: +  AASocket(); +  ~AASocket(); + +  void listen(unsigned short port); +  void connect(const char *ip, unsigned short port); +   +  void send(const char* buf, unsigned int buf_size); +  int receive(char* buf, unsigned int buf_size); + +  void send_string(std::string buf); +  std::string receive_string(); + +	void force_close(); + +private: +  struct sockaddr_in socketaddr; +  int socket; +	int bind_socket; // Tmp socket for listen. +}; + +#endif/*__SOCKET_H__*/ | 
