You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
sems/core/AmCtrlInterface.cpp

277 lines
5.3 KiB

#include "AmCtrlInterface.h"
#include "AmUtils.h"
#include "AmConfig.h"
#include "log.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
AmCtrlInterface* AmCtrlInterface::getNewCtrl()
{
// if(AmConfig::SendMethod == "fifo"){
// return new AmFifoCtrlInterface(p);
// }
// else if(AmConfig::SendMethod == "unix_socket"){
// return new AmUnixCtrlInterface(p);
// }
// ERROR("unknown send method\n");
// return 0;
return new AmUnixCtrlInterface();
}
int AmCtrlInterface::getLine(string& line)
{
int err = get_line(buffer,CTRL_MSGBUF_SIZE);
if(err != -1)
line = buffer;
return err;
}
int AmCtrlInterface::getLines(string& lines)
{
int err = get_lines(buffer,CTRL_MSGBUF_SIZE);
if(err != -1)
lines = buffer;
return err;
}
int AmCtrlInterface::getParam(string& param)
{
return get_param(param,buffer,CTRL_MSGBUF_SIZE);
}
void AmCtrlInterface::consume()
{}
void AmCtrlInterface::close()
{
if((fd != -1) && close_fd){
::close(fd);
}
fd = -1;
}
int AmFifoCtrlInterface::cacheMsg()
{
return 0;
}
int AmFifoCtrlInterface::get_line(char* lb, unsigned int lbs)
{
return fifo_get_line(fp_fifo,lb,lbs);
}
int AmFifoCtrlInterface::get_lines(char* lb, unsigned int lbs)
{
return fifo_get_lines(fp_fifo,lb,lbs);
}
int AmFifoCtrlInterface::get_param(string& p, char* lb, unsigned int lbs)
{
return fifo_get_param(fp_fifo,p,lb,lbs);
}
AmFifoCtrlInterface::AmFifoCtrlInterface()
: AmCtrlInterface(), fp_fifo(NULL)
{
}
AmFifoCtrlInterface::~AmFifoCtrlInterface()
{
close();
}
int AmFifoCtrlInterface::createFifo(const string& addr)
{
const char* fifo_name = addr.c_str();
if( (mkfifo(fifo_name,FIFO_PERM)<0) && (errno!=EEXIST) ) {
ERROR("while creating fifo `%s': %s \n",fifo_name,strerror(errno));
return -1;
}
return 0;
}
int AmFifoCtrlInterface::init(const string& addr)
{
const char* fifo_name = addr.c_str();
if( (mkfifo(fifo_name,FIFO_PERM)<0) && (errno!=EEXIST) ) {
ERROR("while creating fifo `%s': %s \n",fifo_name,strerror(errno));
return -1;
}
if( !(fd = ::open(fifo_name, O_RDONLY)) ) {
ERROR("while opening fifo `%s': %s\n",fifo_name,strerror(errno));
return -1;
}
close_fd = true;
if(!(fp_fifo = fdopen(fd,"r"))){
ERROR("while opening fifo `%s' (fdopen): %s\n",fifo_name,strerror(errno));
return -1;
}
filename = addr;
close_fd = false;
return 0;
}
int AmFifoCtrlInterface::sendto(const string& addr,const char* buf,unsigned int len)
{
return write_to_fifo(addr,buf,len);
}
void AmFifoCtrlInterface::close()
{
if((fp_fifo != NULL) && fp_fifo){
fclose(fp_fifo);
fp_fifo = NULL;
AmCtrlInterface::close();
::unlink(filename.c_str());
}
}
void AmFifoCtrlInterface::consume()
{
while( fifo_get_line(fp_fifo,buffer,CTRL_MSGBUF_SIZE) != 0 ) {
ERROR("consumed from fifo: %s\n",buffer);
}
}
int AmUnixCtrlInterface::cacheMsg()
{
int err_cnt=0;
msg_c = NULL;
while(true){
msg_sz = recv(fd,msg_buf,CTRL_MSGBUF_SIZE,MSG_TRUNC|MSG_DONTWAIT);
if(msg_sz == -1){
ERROR("recv on unix socket failed: %s\n",strerror(errno));
if(++err_cnt >= MAX_MSG_ERR){
ERROR("too many consecutive errors...\n");
return -1;
}
continue;
}
break;
}
if(msg_sz > CTRL_MSGBUF_SIZE){
ERROR("unix socket message is too big (size=%i;max=%i): discarding\n",
msg_sz,CTRL_MSGBUF_SIZE);
return -1;
}
msg_buf[msg_sz-1] = '\0';
msg_c = msg_buf;
DBG("recv-ed: <%s>\n",msg_buf);
return 0;
}
int AmUnixCtrlInterface::get_line(char* lb, unsigned int lbs)
{
assert(msg_c);
return msg_get_line(msg_c,lb,lbs);
}
int AmUnixCtrlInterface::get_lines(char* lb, unsigned int lbs)
{
assert(msg_c);
return msg_get_lines(msg_c,lb,lbs);
}
int AmUnixCtrlInterface::get_param(string& p, char* lb, unsigned int lbs)
{
assert(msg_c);
return msg_get_param(msg_c,p,lb,lbs);
}
AmUnixCtrlInterface::AmUnixCtrlInterface()
: AmCtrlInterface(),msg_c(NULL),msg_sz(0)
{
memset(sock_name,0,UNIX_PATH_MAX);
}
AmUnixCtrlInterface::~AmUnixCtrlInterface()
{
close();
}
int AmUnixCtrlInterface::init(const string& addr)
{
strncpy(sock_name,addr.c_str(),UNIX_PATH_MAX-1);
::unlink(sock_name);
fd = create_unix_socket(sock_name);
if(fd == -1){
ERROR("could not open unix socket '%s'\n",sock_name);
return -1;
}
DBG("AmUnixCtrlInterface::init @ %s\n", sock_name);
close_fd = true;
return 0;
}
int AmUnixCtrlInterface::sendto(const string& addr,const char* buf,unsigned int len)
{
return write_to_socket(fd,addr.c_str(),buf,len);
}
void AmUnixCtrlInterface::close()
{
AmCtrlInterface::close();
if(sock_name[0] != '\0')
::unlink(sock_name);
}
/**
* Return:
* -1 if error.
* 0 if timeout.
* 1 if there some datas ready.
*/
int AmCtrlInterface::wait4data(int timeout)
{
struct pollfd pfd = { fd, POLLIN, 0 };
int ret = poll(&pfd,1,timeout);
if(ret < 0){
ERROR("poll: %s\n",strerror(errno));
return -1;
}
else if(ret == 0){
WARN("poll timed out\n");
return -1;
}
if(pfd.revents & POLLIN)
return 1;
else {
ERROR("poll: revents & POLLIN == 0\n");
return -1;
}
}