![]() |
| | #1 |
| Registered User Join Date: Jan 2009
Posts: 10
| Need help coding a bouncer Code: #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#define MYPORT 3490
#define BACKLOG 10
struct sockaddr_in server;
void *recibir(void *datos);
int socketirc(int sockirc, char *ip, int port);
typedef struct {
int sockirc;
int new_fd;
} data;
void sigchld_handler(int s)
{
while(wait(NULL) > 0);
}
void *recibir(void *datos) {
data *misdatos = (data *) datos;
char recvbuff[130];
int result;
fd_set readset;
memset(&recvbuff, 0, sizeof(recvbuff));
do {
do {
FD_ZERO(&readset);
FD_SET(misdatos->sockirc, &readset);
result = select(misdatos->sockirc + 1, &readset, NULL, NULL, NULL);
} while (result == -1 && errno == EINTR);
if (result > 0) {
if (FD_ISSET(misdatos->sockirc, &readset)) {
result = recv(misdatos->sockirc, recvbuff, sizeof(recvbuff), 0);
if (result == 0) {
close(misdatos->sockirc);
}
else {
if (send(misdatos->new_fd, recvbuff, sizeof(recvbuff), 0) == -1)
perror("send");
}
}
}
else if (result < 0) {
printf("Error on select(): %s", strerror(errno));
}
} while(1);
}
int socketirc(int sockirc, char *ip, int port)
{
if ((sockirc=socket(AF_INET, SOCK_STREAM, 0))==-1){
return;
}
server.sin_addr.s_addr=inet_network(ip);
server.sin_addr.s_addr=inet_addr(ip);
server.sin_family = AF_INET;
server.sin_port = htons(port);
bzero(&(server.sin_zero),8);
if(connect(sockirc, (struct sockaddr *)&server, sizeof(struct sockaddr))==-1){
exit(-1);
}
else
printf("funciona");
return sockirc;
}
main(void)
{
int sockfd, new_fd, sockirc, i, error;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
int sin_size, conectado = 0;
struct sigaction sa;
int yes=1, next = 0, port = 0;
char recvbuff[130], *ptr, ip[15] = "vacio";
struct hostent *h;
data datos;
pthread_t idHilo;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(my_addr.sin_zero), '\0', 8);
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))
== -1) {
perror("bind");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
while(1) {
sin_size = sizeof(struct sockaddr_in);
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
perror("accept");
continue;
}
printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr));
if (!fork()) {
close(sockfd);
memset(&recvbuff, 0, sizeof(recvbuff));
for(;;)
{
if(recv(new_fd, recvbuff, 128, 0))
{
if (strstr(recvbuff, "irc") != NULL && strstr(ip, "vacio")) {
ptr = strtok(recvbuff, " ");
i = 1;
while(ptr != NULL ) {
if (next == 1) {
port = atoi(ptr);
sockirc = socketirc(sockirc, ip, port);
datos.sockirc = sockirc;
datos.new_fd = new_fd;
error = pthread_create (&idHilo, NULL, recibir, (void *) &datos);
next = 0;
break;
}
if (strstr(ptr, "irc") != NULL && strstr(ip, "vacio")) {
if ((h=gethostbyname(ptr)) == NULL) {
herror("gethostbyname");
exit(1);
}
h->h_addr = inet_ntoa(*(struct in_addr*)h->h_addr);
strcpy(ip, h->h_addr);
next = 1;
}
printf("%d\n", i);
i++;
printf("%s\n", ptr);
ptr = strtok(NULL, " ");
}
}
else {
if (send(sockirc, recvbuff, sizeof(recvbuff), 0) == -1)
perror("send");
}
}
}
close(new_fd);
exit(0);
}
close(new_fd);
}
return 0;
}
Thanks in advance. |
| megareix is offline | |
| | #2 |
| and the Hat of Guessing Join Date: Nov 2007
Posts: 8,862
| It is not possible to not be more specific than "it doesn't work". Presumably there is some way that it doesn't work, assuming it compiles; it must fail to connect, or fail to communicate, or fail in some other way. |
| tabstop is offline | |
| | #3 |
| Registered User Join Date: Jan 2009
Posts: 10
| Yes, it compiles. And it can connect to the server. The problem comes then, when I try to join a channel or use any other command. To test it, configure the proxy server type in XChat as wingate. If you have any question, don't hesitate to ask. |
| megareix is offline | |
| | #4 | |
| Registered User Join Date: Apr 2008
Posts: 282
| Quote:
| |
| root4 is offline | |
| | #5 |
| Registered User Join Date: Jan 2009
Posts: 10
| Thanks for the answer root4. I tryed to use netcat as you said, and afer I send the irc server and the port (for example: irc.freenode.net 8001) I get this message over and over again, very fast: Error on select(): Bad file descriptorError on select() And abou the recommendation of add printf(), I did, but I removed all of them to post the code here. I'm completely clueless. I'd like to explain the pthread, because I think there can be any problem in the way I'm using it: I basically create the thread once I'm connected to the irc server, and I pass the socket of the server to de thread function (called recibir). So that function is in an infinite loop waiting to recive information from the irc server. Once it receives information, it pass that information to the client. Meanwhile, the main function waits until the client supplies information so it can pass it to the irc server. I hope to be clear. I'm sorry I don't have a very specific question, but I have no clue about what's the specific problem. It would be very nice if someone takes the time to test it =) Thanks in advance. |
| megareix is offline | |
| | #6 |
| and the hat of Jobseeking Join Date: Aug 2001 Location: The edge of the known universe
Posts: 21,710
| This is just some critique of one function. Some of the issues are elsewhere in the code as well. Code: //!! your datos pointer
//!! what is the scope of that data, does it go out of scope in the thread invoker?
//!! does it get re-used by the thread invoker
//!! does any data used here, get re-used (or say an fd closed) in the invoker?
void *recibir(void *datos) {
data *misdatos = (data *) datos;
char recvbuff[130];
int result;
fd_set readset;
//!! 1. this does nothing useful. Always use the return result of send() / recv()
//!! to determine the amount of valid data.
//!! 2. the & on recvbuff is unnecessary
memset(&recvbuff, 0, sizeof(recvbuff));
do {
do {
FD_ZERO(&readset);
FD_SET(misdatos->sockirc, &readset);
result = select(misdatos->sockirc + 1, &readset, NULL, NULL, NULL);
} while (result == -1 && errno == EINTR);
if (result > 0) {
if (FD_ISSET(misdatos->sockirc, &readset)) {
result = recv(misdatos->sockirc, recvbuff, sizeof(recvbuff), 0);
if (result == 0) {
close(misdatos->sockirc);
//!! again, get out of the loop, you're all done here
}
else {
//!! why sizeof(recvbuff), when you only have "result" bytes?
//!! don't assume that recv always fills the buffer
//!! Also, DON'T assume that send() sends everything on the first
//!! call, it doesn't. You have to check how much was sent, and
//!! if necessary, call send() again with the tail of the unsent
//!! buffer (and a reduced length)
if (send(misdatos->new_fd, recvbuff, sizeof(recvbuff), 0) == -1)
perror("send");
}
}
}
else if (result < 0) {
printf("Error on select(): %s", strerror(errno));
//!! so why are you still in the loop if the connection has closed?
}
} while(1);
}
|
| Salem is offline | |
| | #7 |
| Registered User Join Date: Jan 2009
Posts: 10
| Thanks a lot Salem, the problem is apparently because I send the whole recvbuff instead of "result" bytes. Apparently that was the problem, and now everything works perfect. Here is the new code: Code: #include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#define MYPORT 3490
#define BACKLOG 10
struct sockaddr_in server;
void *recibir(void *datos);
int socketirc(int sockirc, char *ip, int port);
typedef struct {
int sockirc;
int new_fd;
} data;
void sigchld_handler(int s)
{
while(wait(NULL) > 0);
}
void *recibir(void *datos) {
data *misdatos = (data *) datos;
char recvbuff[130];
int result = 0;
fd_set readset;
memset(&recvbuff, 0, sizeof(recvbuff));
do {
do {
FD_ZERO(&readset);
FD_SET(misdatos->sockirc, &readset);
result = select(misdatos->sockirc + 1, &readset, NULL, NULL, NULL);
} while (result == -1 && errno == EINTR);
if (result > 0) {
if (FD_ISSET(misdatos->sockirc, &readset)) {
result = recv(misdatos->sockirc, recvbuff, 128, 0);
if (result == 0) {
close(misdatos->sockirc);
break;
}
else {
if (send(misdatos->new_fd, recvbuff, result, 0) == -1)
perror("send");
}
}
}
else if (result < 0) {
printf("Error on select(): %s", strerror(errno));
break;
}
} while(1);
}
int socketirc(int sockirc, char *ip, int port)
{
if ((sockirc=socket(AF_INET, SOCK_STREAM, 0))==-1){
return;
}
server.sin_addr.s_addr=inet_network(ip);
server.sin_addr.s_addr=inet_addr(ip);
server.sin_family = AF_INET;
server.sin_port = htons(port);
bzero(&(server.sin_zero),8);
if(connect(sockirc, (struct sockaddr *)&server, sizeof(struct sockaddr))==-1){
exit(-1);
}
else
printf("funciona");
return sockirc;
}
main(void)
{
int sockfd, new_fd, sockirc, i, error, result = 0;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
int sin_size, conectado = 0;
struct sigaction sa;
int yes=1, next = 0, port = 0;
char recvbuff[130], *ptr, ip[15] = "vacio";
struct hostent *h;
data datos;
pthread_t idHilo;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(my_addr.sin_zero), '\0', 8);
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))
== -1) {
perror("bind");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
while(1) {
sin_size = sizeof(struct sockaddr_in);
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) {
perror("accept");
continue;
}
printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr));
if (!fork()) {
close(sockfd);
memset(&recvbuff, 0, sizeof(recvbuff));
for(;;)
{
if((result = recv(new_fd, recvbuff, 128, 0)))
{
if (strstr(recvbuff, "irc") != NULL && strstr(ip, "vacio")) {
ptr = strtok(recvbuff, " ");
i = 1;
while(ptr != NULL ) {
if (next == 1) {
port = atoi(ptr);
sockirc = socketirc(sockirc, ip, port);
datos.sockirc = sockirc;
datos.new_fd = new_fd;
error = pthread_create (&idHilo, NULL, recibir, (void *) &datos);
next = 0;
break;
}
if (strstr(ptr, "irc") != NULL && strstr(ip, "vacio")) {
if ((h=gethostbyname(ptr)) == NULL) {
herror("gethostbyname");
exit(1);
}
h->h_addr = inet_ntoa(*(struct in_addr*)h->h_addr);
strcpy(ip, h->h_addr);
next = 1;
}
printf("%d\n", i);
i++;
printf("%s\n", ptr);
ptr = strtok(NULL, " ");
}
}
else {
if (send(sockirc, recvbuff, result, 0) == -1)
perror("send");
}
}
}
close(new_fd);
exit(0);
}
close(new_fd);
}
return 0;
}
Again, thanks a lot Salem =) |
| megareix is offline | |
![]() |
| Thread Tools | |
| Display Modes | |
|
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| The chicken and the egg problem... trying to learn coding but having trouble starting | mothergoose729 | Tech Board | 9 | 03-20-2009 05:22 PM |
| Coding Guideline ....!! | imfeelingfortun | Tech Board | 8 | 10-08-2006 07:09 AM |
| Before Coding | cyberCLoWn | C++ Programming | 16 | 12-15-2003 02:26 AM |
| Coding Contest.... | Koshare | A Brief History of Cprogramming.com | 46 | 10-14-2001 04:32 PM |