// Copyright (C) 2004 Dominic Letourneau
#include "URLHandler.h"
#include <string>
#include <map>
#include "Object.h"
#include "net_types.h"
#include <sstream>
#include <fstream>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "stream_wrap.h"
#include <errno.h>
//@implements core
using namespace std;
namespace FD {
map<string,url_func> &URLHandler::url_table()
{
static map<string,url_func> table;
return table;
}
ObjectRef file_url_handler(const string& url, int flags) {
//FORMAT file:/home/..
int _pos = url.find(":");
string stripped_url = url.substr(_pos + 1, url.size());
switch(flags) {
case URLHandler::URL_READ:
{
ifstream *stream = new ifstream(stripped_url.c_str());
if (stream->fail())
throw new GeneralException("Cannot open file: " + stripped_url, __FILE__, __LINE__);
else
return ObjectRef(new IStream(stream));
}
break;
case URLHandler::URL_WRITE:
{
ofstream *stream = new ofstream(stripped_url.c_str());
if (stream->fail())
throw new GeneralException("Cannot open file: " + stripped_url, __FILE__, __LINE__);
else
return ObjectRef(new OStream(stream));
}
break;
case URLHandler::URL_READWRITE:
{
fstream *stream = new fstream(stripped_url.c_str());
if (stream->fail())
throw new GeneralException("Cannot open file: " + stripped_url, __FILE__, __LINE__);
else
return ObjectRef(new IOStream(stream));
}
break;
default:
ostringstream my_stream;
my_stream<<"Unknown flag "<<flags<<" in file_url_handler";
throw new GeneralException(my_stream.str(),__FILE__,__LINE__);
break;
}
return nilObject;
}
REGISTER_URL_HANDLER(file,file_url_handler);
ObjectRef tcp_url_handler(const string& url, int flags) {
//FORMAT tcp:hostname:port
int _pos = url.find(":");
string stripped_url = url.substr(_pos + 1, url.size());
_pos = stripped_url.find(":");
if (_pos != string::npos) {
stripped_url[_pos] = ' ';
istringstream my_stream(stripped_url);
string host;
int port;
my_stream >> host;
my_stream >> port;
//Create the socket, code taken from TCPConnect
struct sockaddr_in addr;
int fd = socket(PF_INET, SOCK_STREAM, 0);
//int port = 2313;
struct hostent *entp;
memset(&addr, 0, sizeof(struct sockaddr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(0);
if (bind (fd, (struct sockaddr *)&addr, sizeof(addr)))
throw new GeneralException(string("tcp_url_handler bind failed: ") + string(strerror(errno)), __FILE__, __LINE__);
if((entp = gethostbyname(host.c_str())) == NULL)
throw new GeneralException(string("tcp_url_handler Can't get host by name: ") + host, __FILE__, __LINE__);
memcpy(&addr.sin_addr, entp->h_addr_list[0], entp->h_length);
addr.sin_port = htons(port);
if (connect (fd, (struct sockaddr *)&addr, sizeof(addr)))
throw new GeneralException(string("tcp_url_handler connect failed: ") + string(strerror(errno)), __FILE__, __LINE__);
//TODO do something for blocking / non blocking streams, include that into flags?
/*
if (!blocking)
fcntl(fd, F_SETFL, O_NONBLOCK);
*/
//create proper type of stream
switch(flags) {
case URLHandler::URL_READ:
return ObjectRef (new IStream (new fd_istream(fd)));
break;
case URLHandler::URL_WRITE:
return ObjectRef (new OStream (new fd_ostream(fd)));
break;
case URLHandler::URL_READWRITE:
return ObjectRef (new IOStream (new fd_iostream(fd)));
break;
default:
ostringstream my_stream;
my_stream<<"Unknown flags "<<flags<<" in tcp_url_handler";
throw new GeneralException(my_stream.str(),__FILE__,__LINE__);
break;
}
}
else {
throw new GeneralException(string("no port specified for TCP URL : ") + stripped_url,__FILE__,__LINE__);
}
//should not happen...
return nilObject;
}
REGISTER_URL_HANDLER(tcp,tcp_url_handler);
}//namespace FD
syntax highlighted by Code2HTML, v. 0.9.1