📄 scd.c
字号:
#include "global.h"
#define QLEN 32
char * getoptarg = "im:p:";
char * ProgramName = "SCD";
char * version = "0.1";
int port = 7006;
/*print the usage of scc*/
static void usage(char *msg)
{
fprintf(stderr, "%s: usage error: %s\n", ProgramName, msg);
fprintf(stderr, "usage:\t%s [-i] [-p port] [-m max]\n", ProgramName);
fprintf(stderr, "\t-i\tencryption is disable.\n");
fprintf(stderr, "\t-p port\tcause port to be used as the port to bind.\n");
fprintf(stderr, "\t \tthe default value is 6667.\n");
fprintf(stderr, "\t-m max\thow many clients may connect to scd at a time.\n");
fprintf(stderr, "\t \tthe default value is 500\n");
exit(0);
}
/*handle the command line arguments*/
static void parse_args(int argc,char **argv)
{
int argch;
while ((argch = getopt(argc, argv, getoptarg)) != EOF) {
switch (argch) {
case 'm':
/*the max number of user*/
max_user = atoi(optarg);
break;
case 'i':
fprintf(stderr,"encryption disable.\n");
break;
case 'p':
/*the port used as the port to bind*/
port = atoi(optarg);
break;
default:
usage("unrecognized option");
}
}
}
int get_word(FILE * fp,char * name)
{
int c;
int i = 0;
while((c = fgetc(fp)) != EOF
&& c != '\n')
name[i++] = c;
if(c == EOF)
return 0;
name[i] = '\0';
return 1;
}
/*load the information about the user
* already registered*/
void load_user()
{
FILE * fp;
char temp[MAX_NAME];
char * user_name;
int length;
if((fp = fopen(LOG_FILE,"r"))==NULL) {
if((fp=fopen(LOG_FILE,"w+"))==NULL) {
log_err("log file open fail!\n");
}
}
while(get_word(fp,temp)) {
length = strlen(temp)+2;
user_name = (char *)malloc(sizeof(char)*length);
if(user_name == NULL) {
log_err("malloc fail!\n");
}
strncpy(user_name,temp,length);
hash_insert(user_name);
}
}
/*used to debug the program*/
void print_l()
{
int i;
bucket_list p;
for(i = 0; i < SIZE; i++) {
p = hash_table[i];
while(p) {
fprintf(stderr,"%s,%d\n",p->name,p->connfd);
p = p->next;
}
}
fprintf(stderr,"\n");
}
void print_a()
{
int i;
addr_list p;
for(i = 0; i < SIZE; i++) {
p = addr_table[i];
while(p) {
fprintf(stderr,"%s,%d\n",p->name,p->connfd);
p = p->next;
}
}
fprintf(stderr,"\n");
}
int passivesock(const char *transport, int qlen)
{
struct servent * pse; /* pointer to service information entry */
struct protoent *ppe; /* pointer to protocol information entry*/
struct sockaddr_in sin;
int s, type;
char * service = "scd";
char error[MAX_ERR];
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = port;
/* Map protocol name to protocol number */
if ( (ppe = getprotobyname(transport)) == 0)
fprintf(stderr,"can't get \"%s\" protocol entry\n", transport);
/* Use protocol to choose a socket type */
if (strcmp(transport, "udp") == 0) type = SOCK_DGRAM;
else type = SOCK_STREAM;
/* Allocate a socket */
s = socket(PF_INET, type, ppe->p_proto);
if (s < 0) {
sprintf(error,"can't create socket: %s\n", strerror(errno));
log_err(error);
}
/* Bind the socket */
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
sprintf(error,"can't bind to %s port: %s\n", service,strerror(errno));
log_err(error);
}
if (type == SOCK_STREAM && listen(s, qlen) < 0) {
sprintf(error,"can't listen on %s port: %s\n", service,strerror(errno));
log_err(error);
}
return s;
}
/*initialize the mutexes*/
void init_mutex()
{
int res;
if((res=pthread_mutex_init(&num_mutex,NULL))!=0) {
log_err("mutex init fail!\n");
}
if((res=pthread_mutex_init(&addr_mutex,NULL))!=0) {
log_err("mutex init fail!\n");
}
if((res=pthread_mutex_init(&name_mutex,NULL))!=0) {
log_err("mutex init fail!\n");
}
if((res=pthread_mutex_init(&host_mutex,NULL))!=0) {
log_err("mutex init fail!\n");
}
}
/*version handshake*/
void version_mes(int connfd)
{
char temp[MAX_VERSION];
sprintf(temp,"SCD Version: %s",version);
send_mes(temp,connfd);
}
/*record the host name into the link list*/
void host_insert(int connfd,char *host)
{
host_list * temp;
temp = (host_list *)malloc(sizeof(host_list));
if(temp == NULL) {
log_err("malloc fail!\n");
}
temp->connfd = connfd;
temp->host = host;
pthread_mutex_lock(&host_mutex);
if(host_tail == NULL) {
host_head = temp;
host_tail = temp;
} else {
host_tail->next = temp;
temp->next = NULL;
}
pthread_mutex_unlock(&host_mutex);
}
/*delete the host name from the link list*/
host_list * host_delete(int connfd)
{
host_list * p1;
host_list * p2;
int ok = 0;
pthread_mutex_lock(&host_mutex);
p1 = host_head;
p2 = host_head;
while(p2) {
if(p2->connfd == connfd) {
ok = 1;
break;
}
p1 = p2;
p2 = p2->next;
}
if(ok) {
if(host_head == host_tail) {
host_head = NULL;
host_tail = NULL;
} else if(p2 == host_head) {
host_head = host_head->next;
} else if(p2 == host_tail) {
host_tail = p1;
p1->next = NULL;
} else
p1->next = p2->next;
}
pthread_mutex_unlock(&host_mutex);
if(ok) return p2;
else return NULL;
}
/*let the program to become a daemon program*/
int daemon_init()
{
pid_t pid;
if( (pid = fork()) < 0)
return -1;
else if(pid != 0) /* parent exit */
exit(0);
setsid();
umask(0);
/* close stdin, stdout and stderr*/
freopen("/dev/null", "r", stdin);
freopen("/dev/null", "w", stdout);
freopen("/dev/null", "w", stderr);
return 0;
}
void log_err(char * message)
{
FILE * fp;
#ifdef Debug
fprintf(stderr,"%s\n",message);
#else
if((fp = fopen(LOG_ERR,"w")) == NULL) {
exit(1);
}
fprintf(fp,"%s\n",message);
fclose(fp);
#endif
exit(1);
}
int main(int argc,char **argv)
{
int i;
int res;
pthread_t tid;
pthread_attr_t thread_attr;
struct sockaddr_in fsin;
unsigned int alen;
int msock;
int ssock;
char error[MAX_ERR];
char temphost[MAX_HOST];
char * host;
parse_args(argc,argv);
daemon_init();
init_mutex();
#ifdef Debug
fprintf(stderr,"max: %d\n",max_user);
fprintf(stderr,"port: %d\n",port);
#endif
init_hash_tab();
load_user();
msock = passivesock("tcp", QLEN);
if((res=pthread_attr_init(&thread_attr)) != 0) {
log_err("Attribute creation fails!\n");
}
if((res=pthread_attr_setdetachstate(&thread_attr,
PTHREAD_CREATE_DETACHED)) != 0) {
log_err("Seting detach attribute fails!\n");
}
while (1) {
alen = sizeof(fsin);
ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
if (ssock < 0) {
if (errno == EINTR) continue;
//fprintf(stderr,"accept: %s\n", strerror(errno));
}
/*check the max number of connect user*/
pthread_mutex_lock(&num_mutex);
if(on_line_num == max_user) {
pthread_mutex_unlock(&num_mutex);
sprintf(error,"ERR: 104");
send_mes(error,ssock);
continue;
} else {
on_line_num++;
pthread_mutex_unlock(&num_mutex);
version_mes(ssock);
}
inet_ntop(AF_INET,&fsin.sin_addr,temphost,sizeof(temphost));
host = (char *)malloc((strlen(temphost)+2)*sizeof(char));
if(host == NULL) {
log_err("malloc fail!\n");
}
strcpy(host,temphost);
host_insert(ssock,host);
if((res=pthread_create(&tid,&thread_attr,(void * (*)(void *))receive_mes, (void *)ssock)) != 0) {
log_err("Creating thread fail!\n");
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -