/** @file uds.c @date 2009-03-19 @author 오재경 freefrug@falinux.com @brief uds 를 사용한 통신을 담당한다. @modify 2009-12-11 (오재경) uds_open_client() 함수에 대한 편의성을 가미했다. uds_open_client() 함수 호출시 인자의 파일이름은 uds_write() 함수에서 목적지가 NULL 일 경우 목적지로 대치된다. @todo @bug @remark @warning */ // // 저작권 에프에이리눅스(주) // 외부공개 금지 // //---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include #include char desc_uds[] = "falinux uds ver 0.2.0"; /// uds 개별 구조체 typedef struct { char port[256]; int im_server; } uds_priv_t; static poll_obj_t *tmp_uds_poll = NULL; // poll 관리객체없이 전송함수를 위해 //------------------------------------------------------------------------------ /** @brief uds 소켓을 서버형태로 open 한다. @param fname 문자열 파일이름 @return poll_obj_t 형태의 포인터 *///---------------------------------------------------------------------------- poll_obj_t *uds_open_server( char *fname ) { struct sockaddr_un addr_svr; poll_obj_t *obj; uds_priv_t *uds; int option; int sockfd; sockfd = socket( AF_UNIX, SOCK_DGRAM, 0 ); if ( sockfd < 0 ) { perror( "uds open error:" ); return NULL; } // 이미 소켓용 화일에 링크되어 있다면 제거한다. unlink ( fname ); // TIME-WAIT 상태에 있는 소켓에 할당되어 있는 IP 주소와 포트를 바로 사용할 수 있도록 // SO_REUSEADDR 의 옵션 값을 TRUE 로 option = 1; setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); // 소켓을 시스템에 연결한다. bzero( &addr_svr, sizeof(struct sockaddr_un) ); addr_svr.sun_family = AF_UNIX; strcpy( addr_svr.sun_path, fname ); if( bind( sockfd, (struct sockaddr *)&addr_svr, sizeof(struct sockaddr_un) ) < 0 ) { perror("uds bind error :"); close( sockfd ); return NULL; } // uds 만의 정보를 설정한다. uds = (uds_priv_t *)malloc( sizeof(uds_priv_t) ); uds->im_server = 1; strcpy( uds->port, fname ); obj = poll_add( sockfd ); obj->type = STYP_UDS; obj->priv = (void *)uds; tmp_uds_poll = obj; return obj; } //------------------------------------------------------------------------------ /** @brief uds 소켓을 클라이언트 형태로 open 한다. @param fname 문자열 파일이름, 확장을 위해 존재하며 NULL 을 사용하여도 된다. @return poll_obj_t 형태의 포인터 *///---------------------------------------------------------------------------- poll_obj_t *uds_open_client( char *fname ) { poll_obj_t *obj; uds_priv_t *uds; int sockfd; sockfd = socket( AF_UNIX, SOCK_DGRAM, 0 ); if ( sockfd < 0 ) { perror( "uds open error:" ); return NULL; } // uds 만의 정보를 설정한다. uds = (uds_priv_t *)malloc( sizeof(uds_priv_t) ); uds->im_server = 0; if (fname) { strcpy( uds->port, fname ); } obj = poll_add( sockfd ); obj->type = STYP_UDS; obj->priv = (void *)uds; tmp_uds_poll = obj; return obj; } //------------------------------------------------------------------------------ /** @brief uds 소켓을 close 한다. @param obj 폴객체 포인터 *///---------------------------------------------------------------------------- void uds_close( poll_obj_t *obj ) { close( obj->fd ); if ( obj->priv ) { free( obj->priv ); } poll_delete( obj ); if ( tmp_uds_poll == obj ) tmp_uds_poll = NULL; } //------------------------------------------------------------------------------ /** @brief uds 폴객체를 파일이름으로 찾는다. @param fname 문자열 파일이름 @return obj 폴객체 포인터 *///---------------------------------------------------------------------------- poll_obj_t *uds_get_byport( char *fname ) { poll_obj_t *obj; uds_priv_t *uds; int idx, count; count = poll_count(); for(idx=0; idxpriv; if ( uds ) { if ( 0 == strcmp( uds->port, fname ) ) { return obj; } } } return NULL; } //------------------------------------------------------------------------------ /** @brief uds 소켓을 통해 데이타를 전송한다. @param obj 폴객체 포인터 @param to 상대방 파일이름 문자열포인터 @param buf 전송버퍼 @param len 버퍼의 길이 @return 전송한 데이타 개수 *///---------------------------------------------------------------------------- int uds_write( poll_obj_t *obj, char *to, char *buf, int len ) { uds_priv_t *uds; struct sockaddr_un uds_addr; char *dst; int wrcnt; uds = (uds_priv_t *)obj->priv; // 클라이언트로 열려있거나 목적지가 존재하지 않으면 저장된 포트로 전송한다. dst = to; if ( ( 0 == uds->im_server ) && ( NULL == dst ) ) { dst = uds->port; } // 상대편 주소를 설정한다. bzero( &uds_addr, sizeof(struct sockaddr_un) ); uds_addr.sun_family = AF_UNIX; strcpy( uds_addr.sun_path, dst ); // 전송한다. wrcnt = sendto( obj->fd, buf, len, 0, (struct sockaddr *)&uds_addr, sizeof(uds_addr) ); if ( 0 > wrcnt ) { char msg[256]; sprintf( msg, "uds send error(to %s)", dst ); perror( msg ); } return wrcnt; } //------------------------------------------------------------------------------ /** @brief uds 소켓을 통해 데이타를 읽는다. @param obj 폴객체 포인터 @param buf 전송버퍼 @param len 버퍼의 길이 @return 전송된 데이타 개수 *///---------------------------------------------------------------------------- int uds_read( poll_obj_t *obj, char *buf, int len ) { struct sockaddr_un uds_addr; int addr_len; int rdcnt; // 데이타를 읽는다. addr_len = sizeof(uds_addr); rdcnt = recvfrom( obj->fd, buf, len, 0, (struct sockaddr *)&uds_addr, (socklen_t *)&addr_len ); if ( 0 > rdcnt ) { perror( "uds recv error:" ); } //else //{ // if ( from ) strcpy( from, uds_addr.sun_path ); //} return rdcnt; } //------------------------------------------------------------------------------ /** @brief poll 객체없이 uds 소켓을 통해 데이타를 전송한다. @param to 상대방 파일이름 문자열포인터 @param buf 전송버퍼 @param len 버퍼의 길이 @return 전송한 데이타 개수 @remark uds_open_server(), uds_open_client() 함수는 한번 호출되어야 한다. *///---------------------------------------------------------------------------- int uds_write_simple( char *to, char *buf, int len ) { if ( tmp_uds_poll ) { return uds_write( tmp_uds_poll, to, buf, len ); } return -1; } //------------------------------------------------------------------------------ /** @brief poll 객체없이 uds 소켓을 통해 데이타를 읽는다. @param buf 전송버퍼 @param len 버퍼의 길이 @return 전송된 데이타 개수 @remark uds_open_server(), uds_open_client() 함수는 한번 호출되어야 한다. *///---------------------------------------------------------------------------- int uds_read_simple( char *buf, int len ) { if ( tmp_uds_poll ) { return uds_read( tmp_uds_poll, buf, len ); } return -1; }