Main Page   Modules   Class Hierarchy   Compound List   File List   Compound Members   Related Pages  

freedb_remote.cxx

00001 #include <freedb/freedb.hxx>
00002 
00005 FreedbRemote::FreedbRemote(string servername = "freedb.freedb.org")
00006     :   _sockfd(-1)
00007 {
00008     connect(servername);
00009 }
00010 
00015 FreedbRemote::~FreedbRemote()
00016 {
00017     disconnect();
00018 }
00019 
00028 void FreedbRemote::sendCommand(string command) const
00029 {
00030     command += "\n";
00031     int retval = send(_sockfd, command.data(), command.length(), 0);
00032 }
00033 
00048 string FreedbRemote::getResponseLine(bool stripcr = true) const
00049 {
00050     string response;
00051     char buf;
00052     int retval;
00053 
00054     while (buf != '\n')
00055     {
00056         retval = recv(_sockfd, (void *)&buf, 1, 0);
00057 
00058         if (buf != '\r' || stripcr == false)
00059         {
00060             response += buf;
00061         }
00062     }
00063 
00064     return(response);
00065 }
00066 
00086 void FreedbRemote::connect(string servername = "freedb.freedb.org")
00087 {
00088     struct sockaddr_in saddr;
00089     struct hostent* dns;
00090     int addrlen = sizeof(struct sockaddr);
00091 
00092     _sockfd = socket(PF_INET, SOCK_STREAM, 0);
00093 
00094     if (_sockfd == (-1))
00095     {
00096         Error err;
00097 
00098         err.errcode = errno;
00099         err.errmsg = strerror(errno);
00100 
00101         throw err;
00102     }
00103 
00104     dns = gethostbyname(servername.c_str());
00105 
00106     if (dns == NULL)
00107     {
00108         Error err;
00109 
00110         switch (h_errno)
00111         {
00112             case HOST_NOT_FOUND:
00113                 err.errmsg = "Host not found";
00114             break;
00115 
00116             case NO_ADDRESS:
00117                 err.errmsg = "Host has no IP-Adress";
00118             break;
00119 
00120             case NO_RECOVERY:
00121                 err.errmsg = "Permanent DNS server error";
00122             break;
00123 
00124             case TRY_AGAIN:
00125                 err.errmsg = "Temporary DNS server error";
00126             break;
00127 
00128             default:
00129                 err.errmsg = "Unknown error";
00130         }
00131 
00132         throw err;
00133     }
00134 
00135     saddr.sin_family = AF_INET;
00136     saddr.sin_port = htons(CDDBP_PORT);
00137     saddr.sin_addr = *((struct in_addr *)dns->h_addr_list[0]);
00138 
00139 
00140     int retval = ::connect(_sockfd, (struct sockaddr *)&saddr, addrlen);
00141     if (retval == (-1))
00142     {
00143         //assert(errno != EISCONN);
00144         Error err;
00145 
00146         err.errcode = errno;
00147         err.errmsg = strerror(errno);
00148 
00149         throw err;
00150     }
00151 
00152 
00153     /* socket is connected */
00154     string response = getResponseLine();
00155 
00156     if (response.substr(0, 2) != "20")
00157     {
00158         Error err;
00159         err.errcode = stoi(response.substr(0, 3));
00160 
00161         switch (err.errcode)
00162         {
00163             case 432:
00164                 err.errmsg = "Permission denied";
00165             break;
00166 
00167             case 433:
00168                 err.errmsg = "Too many users";
00169             break;
00170 
00171             case 434:
00172                 err.errmsg = "System load too high";
00173             break;
00174 
00175             default:
00176                 err.errmsg = "Unknown error";
00177         }
00178 
00179         err.extinfo = response;
00180 
00181         throw err;
00182     }
00183 
00184     cout << response;
00185 
00186     _greeting = response;
00187 }
00188 
00191 void FreedbRemote::disconnect()
00192 {
00193     if (_sockfd != -1)
00194         {
00195         sendCommand("quit");
00196 
00197         int retval = close(_sockfd);
00198         if (retval == (-1))
00199         {
00200             Error err;
00201             err.errcode = errno;
00202             err.errmsg = strerror(errno);
00203             throw err;
00204         }
00205     }
00206 }
00207 
00220 void FreedbRemote::doHandshake(string username, string clientname, string version) const
00221 {
00222     char* hn = new char[256];
00223     int retval = gethostname(hn, 256);
00224     if (retval == (-1))
00225     {
00226         Error err;
00227         err.errcode = errno;
00228         err.errmsg = strerror(errno);
00229         throw err;
00230     }
00231 
00232     /* send handshake */
00233     string hostname = hn;
00234     string handshake = "cddb hello " + username + " " + hostname + " " + clientname + " " + version;
00235 
00236     sendCommand(handshake);
00237 
00238     /* get response */
00239     string response = getResponseLine();
00240 
00241     if (response.substr(0, 2) != "20")
00242     {
00243         Error err;
00244         err.errcode = stoi(response.substr(0, 3));
00245 
00246         switch (err.errcode)
00247         {
00248             case 431:
00249                 err.errmsg = "Handshake not successful";
00250             break;
00251 
00252             case 402:
00253                 err.errmsg = "Already shook hands";
00254             break;
00255 
00256             default:
00257                 err.errmsg = "Unknown error";
00258         }
00259 
00260         err.extinfo = response;
00261 
00262         throw err;
00263     }
00264 }
00265 
00266 ServerInfo FreedbRemote::parseServerInfoLine(string line)
00267 {
00268     ServerInfo info;
00269     int lastpos = 0, currentpos;
00270 
00271     if (line[0] == '\n')
00272     {
00273         line = line.substr(1, line.length() - 1);
00274     }
00275 
00276     //site hostname
00277     currentpos = line.find(" ", lastpos);
00278     info.site = line.substr(lastpos, currentpos);
00279     lastpos = currentpos + 1;
00280 
00281     //port
00282     currentpos = line.find(" ", lastpos);
00283     info.port = stoi(line.substr(lastpos, currentpos));
00284     lastpos = currentpos + 1 ;
00285 
00286     //latitude
00287     currentpos = line.find(" ", lastpos);
00288     string latitude = line.substr(lastpos, currentpos);
00289     lastpos = currentpos + 1 ;
00290     info.latitude.compassdirection = latitude.substr(0, 1);
00291     info.latitude.degrees = stoi(latitude.substr(1, 3));
00292     info.latitude.minutes = stoi(latitude.substr(5, 2));
00293 
00294     //longitude
00295     currentpos = line.find(" ", lastpos);
00296     string longitude = line.substr(lastpos, currentpos);
00297     lastpos = currentpos + 1 ;
00298     info.longitude.compassdirection = longitude.substr(0, 1);
00299     info.longitude.degrees = stoi(longitude.substr(1, 3));
00300     info.longitude.minutes = stoi(longitude.substr(5, 2));
00301 
00302     //description
00303     info.description = line.substr(lastpos, line.length() - lastpos);
00304 
00305     return(info);
00306 }
00307 
00308 
00309 vector<ServerInfo> FreedbRemote::getServerList() const
00310 {
00311     vector<ServerInfo> servers;
00312 
00313     sendCommand("sites");
00314 
00315     string response = getResponseLine();
00316 
00317     if (response.substr(0, 1) != "2")
00318     {
00319         Error err;
00320         err.errcode = stoi(response.substr(0, 3));
00321 
00322         switch (err.errcode)
00323         {
00324             case 401:
00325                 err.errmsg = "No site information available";
00326             break;
00327 
00328             default:
00329                 err.errmsg = "Unknown error";
00330         }
00331 
00332         err.extinfo = response;
00333 
00334         throw err;
00335     }
00336 
00337     char buf;
00338     bool newline = false;
00339     int lines = 0, retval;
00340 
00341     response = "";
00342 
00343     while (1)
00344     {
00345         retval = recv(_sockfd, (void *)&buf, 1, 0);
00346 
00347         if (buf == '.' && newline == true)
00348         {
00349             break;
00350         }
00351 
00352         if (buf == '\n')
00353         {
00354             newline = true;
00355             lines++;
00356 
00357             servers.push_back(parseServerInfoLine(response));
00358 
00359             response = "";
00360         }
00361         else
00362         {
00363             newline = false;
00364         }
00365 
00366         if (buf != '\r')
00367         {
00368             response += buf;
00369         }
00370     }
00371 
00372     return(servers);
00373 }
00374 
00375 
00376 vector<string> FreedbRemote::getCategories() const
00377 {
00378     vector<string> categories;
00379 
00380     sendCommand("lscat");
00381 
00382     string response = getResponseLine();
00383 
00384     if (response.substr(0, 3) != "210")
00385     {
00386         Error err;
00387         err.errcode = stoi(response.substr(0, 3));
00388 
00389         switch (err.errcode)
00390         {
00391             default:
00392                 err.errmsg = "Unknown error";
00393         }
00394 
00395         err.extinfo = response;
00396 
00397         throw err;
00398     }
00399 
00400     char buf;
00401     bool newline = false;
00402     int lines = 0, retval;
00403 
00404     response = "";
00405 
00406     while (1)
00407     {
00408         retval = recv(_sockfd, (void *)&buf, 1, 0);
00409 
00410         if (buf == '.' && newline == true)
00411         {
00412             break;
00413         }
00414 
00415         if (buf == '\n')
00416         {
00417             newline = true;
00418             lines++;
00419 
00420             categories.push_back(response);
00421 
00422             response = "";
00423         }
00424         else
00425         {
00426             newline = false;
00427         }
00428 
00429         if (buf != '\r')
00430         {
00431             response += buf;
00432         }
00433     }
00434 
00435     return(categories);
00436 }
00437 
00438 
00439 vector<SearchResult> FreedbRemote::search() const
00440 {
00441 }

Generated on Wed Nov 6 17:32:02 2002 for libfreedb by doxygen1.2.18