I'm writing a server that takes connections over a socket
Code:
int raw_tcp_listen(int port)
{
int sock;
if((sock=socket(AF_INET,SOCK_STREAM,0))<0)
{perror("socket err");return -1;}
#ifdef FULL_DEBUG
else
printf("socket\n");
#endif
struct sockaddr_in sin;
memset(&sin,0,sizeof(sin));
sin.sin_addr.s_addr=INADDR_ANY;
sin.sin_family=AF_INET;
sin.sin_port=htons(port);
int RAval=1;
if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&RAval,sizeof(RAval)) != 0)
{perror("reuse set err");return -1;}
#ifdef FULL_DEBUG
else
printf("reuse addr set\n");
#endif
linger ling;
ling.l_onoff=0;
ling.l_linger=1;
if (setsockopt(sock,SOL_SOCKET,SO_LINGER,&ling,sizeof(ling)) != 0)
{perror("linger set err");return -1;}
#ifdef FULL_DEBUG
else
printf("linger set\n");
#endif
if(bind(sock,(struct sockaddr *)&sin,sizeof(sin))!=0)
{perror("bind err");return -1;}
#ifdef FULL_DEBUG
else
printf("bind\n");
#endif
#ifdef FULL_DEBUG
printf("listening to socket\n");
#endif
if (listen(sock,2) != 0)
{perror("listen err");return -1;}
#ifdef FULL_DEBUG
else
printf("listen\n");
#endif
return(sock);
}
typedef struct {
int err;
int port;
} l_raw_t;
void *listening_function_raw(void *ptr)
{
l_raw_t ipt = *(l_raw_t*)(ptr);
int id =-1;
int err = ipt.err;
int port=ipt.port;
while ((err) && (keep_on)) {
int l_sd=raw_tcp_listen(port);
if (l_sd > 0) {
struct sockaddr_in csa;
memset(&csa,0,sizeof(csa));
socklen_t clen=sizeof(csa);
int sd = accept(l_sd, (struct sockaddr*)&csa,&clen);
if (close(l_sd) != 0)
{perror("l_socket close");err=0;}
if (sd < 0) {
{perror("accept");err=0;}
} else {
printf ("accepted\n");
}
if (getpeername(sd,(struct sockaddr*)&csa,&clen) != 0)
{perror("get ip");err=0;}
char *c_ip = inet_ntoa(csa.sin_addr);
printf("%s\n",c_ip);
if (err) {
int test=1;
if (
//make sure I know whois
(strcmp("xxx.xxx.xxx.xxx",c_ip) != 0)
)
test=0;
if (test) {
pthread_mutex_lock(&con_cnt_mutex);
id=con_cnt;
++con_cnt;
pthread_mutex_unlock(&con_cnt_mutex);
#ifdef FULL_DEBUG
printf("raw %i connected\n",id);
#endif
printf("%s=raw %i\n",c_ip,id);
pthread_mutex_lock(&raw_table_mutex);
raw_table_t raw_add;
raw_add.sd=sd;
raw_add.id=id;
raw_add.state=1;
raw_table.push_back(raw_add);
pthread_mutex_unlock(&raw_table_mutex);
pthread_attr_t io_attr;
pthread_attr_init(&io_attr);
pthread_attr_setdetachstate(&io_attr,PTHREAD_CREATE_DETACHED);
pthread_t tid;
pthread_create
(&tid, &io_attr,&io_function_raw, (void *) &id );
}
}
err=1;
} else sleep(1);
}
pthread_exit(NULL);
}
and then splits a thread off to run a command....
Code:
void *io_function_raw(void *ptr)
{
int id= *(int *)ptr;
int found=0;
pthread_mutex_lock(&raw_table_mutex);
for (int s=0;s < raw_table.size();s++)
if (raw_table.at(s) == id) {
raw_table.at(s).tid=pthread_self();
found=1;
}
pthread_mutex_unlock(&raw_table_mutex);
if (found) {
while (keep_on) {
int sd;
int good=0;
pthread_mutex_lock(&raw_table_mutex);
for (int s=0;s < raw_table.size();s++)
if (raw_table.at(s) == id) {
sd=raw_table.at(s).sd;
if (raw_table.at(s).active())
good=1;
break;
}
pthread_mutex_unlock(&raw_table_mutex);
if (!good) {
#ifdef FULL_DEBUG
printf("raw %i read error: R0062\n",id);
#endif
break;
}
#ifdef FULL_DEBUG
printf("raw %i waiting for command\n",id);
#endif
int err=0;
char buf[100000]="";
//read here
err=read(sd,buf,99999);
if (err > 0) {
#ifdef FULL_DEBUG
printf("raw %i got command string len: %i\n",id,strlen(buf));
#endif
pthread_mutex_lock(&exec_cnt_mutex);
int eid = exec_cnt;
++exec_cnt;
pthread_mutex_unlock(&exec_cnt_mutex);
pthread_mutex_lock(&exec_table_mutex);
exec_table_t exec_add;
exec_add.id=eid;
exec_add.cid=id;
//strcpy(exec_add.cmdstring,strdup(buf));
exec_add.cmdstring = strdup(buf);
exec_add.cmeth=raw_w_type;
exec_add.state=1;
exec_table.push_back(exec_add);
pthread_mutex_unlock(&exec_table_mutex);
pthread_attr_t exec_attr;
pthread_attr_init(&exec_attr);
pthread_attr_setdetachstate(&exec_attr,PTHREAD_CREATE_DETACHED);
pthread_t scmd;
int scmd_tid;
scmd_tid = pthread_create
(&scmd,&exec_attr,&execute_command_string,(void *) &eid);
#ifdef FULL_DEBUG
printf("ran exec\n");
#endif
} else {
#ifdef FULL_DEBUG
printf("raw %i read error: R0065\n",id);
#endif
pthread_mutex_lock(&raw_table_mutex);
for (int s=0;s < raw_table.size();s++)
if (raw_table.at(s) == id) {
raw_table.at(s).state=0;
break;
}
pthread_mutex_unlock(&raw_table_mutex);
break;
}
}
}
RAW_end(id);
pthread_exit(NULL);
}
///function that selects command based on input
runs a the function for the command itself no thread out of here
and that all works fine.....
now, what I want to do is be able to set up a command to run specific things off of the CLI.... since I can't expect all the code I want to run to drop in source instantly(if ever)
and what I want to do for that... is in the command's thread forck off and exec
which I have working....
Code:
int cli_stdout[2];
if (pipe(cli_stdout) == -1) {
std::cerr << cli_cmd.name << ": pipe error" << std::endl;
cli_cmd.deactivate();
}
cli_pid=fork();
switch (cli_pid) {
case -1:
std::cerr << cli_cmd.name << ": fork error" << std::endl;
break;
case 0: //child
if (close(cli_stdout[0]) == -1)
std::cerr << cli_cmd.name << ": c00 error" << std::endl;
if (dup2(cli_stdout[1], STDOUT_FILENO) == -1)
std::cerr << cli_cmd.name << ": dup error" << std::endl;
if (close(cli_stdout[1]) == -1)
std::cerr << cli_cmd.name << ": c10 error" << std::endl;
if (execvp(cmd_name,cmd_arr) == -1) {
std::cerr << cli_cmd.name << ": exec error" << std::endl;
cli_cmd.deactivate();
_exit(42);
} else _exit(45);
break;
default: //parent
if (close(cli_stdout[1]) == -1)
std::cerr << cli_cmd.name << ": c11 error" << std::endl;
cli_cmd << "started\n";
cli_cmd.send();
cli_cmd.empty();
while (cli_cmd.active()) {
char cli_iobuf[500]="";
if (read(cli_stdout[0],cli_iobuf,500) <= 0) {
cli_cmd.deactivate();
std::cerr << cli_cmd.name << ": read error" << std::endl;
} else {
cli_cmd << cli_iobuf;
cli_cmd.send();
cli_cmd.empty();
}
}
if (close(cli_stdout[0]) == -1)
std::cerr << cli_cmd.name << ": c01 close error" << std::endl;
break;
}
if (kill(cli_pid,SIGKILL) != 0)
std::cerr << cli_cmd.name << ": kill error" << std::endl;
cli_cmd.clear();
std::cout << cli_cmd.name << ": ended" << std::endl;
}
}
the only problem is.... that once the fork is open it only accepts one more socket and then I start getting bind err: Address already in use
once the fork ends one way or another (exit or kill) the socket is able to be attached to again....
I assume this is due to something in the fork environment cloning.... I just haven't hacked it quite that deep....
and was hoping someone out ther could help either waylay or at least guide me in that process.
and, yeah... I know I kinda just gave sporadic pieces of the code, but this is already too long.... let me know if I missed something
oh yeah... and I've taken the exec completely out and just done for () cout << stuff; exit.... that didn't change it.... so I don't think it's that.