// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: acquire-method.cc,v 1.2 1998/11/01 05:27:30 jgg Exp $
+// $Id: acquire-method.cc,v 1.3 1998/11/01 08:07:11 jgg Exp $
/* ######################################################################
Acquire Method
exit(100);
SetNonBlock(STDIN_FILENO,true);
+
+ Queue = 0;
}
/*}}}*/
// AcqMethod::Fail - A fetch has failed /*{{{*/
if (Single == false)
if (WaitFd(STDIN_FILENO) == false)
return 0;
- }
-
- if (ReadMessages(STDIN_FILENO,Messages) == false)
- return 0;
+ if (ReadMessages(STDIN_FILENO,Messages) == false)
+ return 0;
+ }
+
// Single mode exits if the message queue is empty
if (Single == true && Messages.empty() == true)
return 0;
// Append it to the list
FetchItem **I = &Queue;
- for (; *I != 0 && (*I)->Next != 0; I = &(*I)->Next);
+ for (; *I != 0; I = &(*I)->Next);
*I = Tmp;
+ cout << "GOT " << Tmp->Uri << endl;
if (Fetch(Tmp) == false)
Fail();
// sprintf the description
char S[1024];
- unsigned int Len = snprintf(S,sizeof(S),"101 Log\nURI: %s\n"
+ unsigned int Len = snprintf(S,sizeof(S),"101 Status\nURI: %s\n"
"Message: ",CurrentURI.c_str());
vsnprintf(S+Len,sizeof(S)-Len,Format,args);
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: http.cc,v 1.1 1998/11/01 05:30:47 jgg Exp $
+// $Id: http.cc,v 1.2 1998/11/01 08:07:13 jgg Exp $
/* ######################################################################
HTTP Aquire Method - This is the HTTP aquire method for APT.
in_addr LastHostA;
bool ServerState::Open()
{
+ // Use the already open connection if possible.
+ if (ServerFd != -1)
+ return true;
+
Close();
- int Port;
+ int Port = 80;
string Host;
- if (Proxy.empty() == false)
+ if (Proxy.empty() == true)
{
- Port = ServerName.Port;
+ if (ServerName.Port != 0)
+ Port = ServerName.Port;
Host = ServerName.Host;
}
else
{
- Port = Proxy.Port;
+ if (Proxy.Port != 0)
+ Port = Proxy.Port;
Host = Proxy.Host;
}
// Lookup the host
hostent *Addr = gethostbyname(Host.c_str());
if (Addr == 0)
- return _error->Errno("gethostbyname","Could not lookup host %s",Host.c_str());
+ return _error->Error("Could not resolve '%s'",Host.c_str());
LastHost = Host;
LastHostA = *(in_addr *)(Addr->h_addr_list[0]);
}
/*}}}*/
// ServerState::RunHeaders - Get the headers before the data /*{{{*/
// ---------------------------------------------------------------------
-/* */
-bool ServerState::RunHeaders()
+/* Returns 0 if things are OK, 1 if an IO error occursed and 2 if a header
+ parse error occured */
+int ServerState::RunHeaders()
{
State = Header;
Result = 0;
Size = 0;
StartPos = 0;
- Encoding = Closes;
+ Encoding = Closes;
+ HaveContent = false;
time(&Date);
do
string::const_iterator J = I;
for (; J != Data.end() && *J != '\n' && *J != '\r';J++);
if (HeaderLine(string(I,J-I)) == false)
- return false;
+ return 2;
I = J;
}
- return true;
+ return 0;
}
while (Owner->Go(false,this) == true);
-
- return false;
+
+ return 1;
}
/*}}}*/
// ServerState::RunData - Transfer the data from the socket /*{{{*/
while ((Last = Owner->Go(false,this)) == true);
if (Last == false)
return false;
- }
+ }
}
else
{
string Tag = string(Line,0,Pos);
string Val = string(Line,Pos+1);
- if (stringcasecmp(Tag,"HTTP") == 0)
+ if (stringcasecmp(Tag.begin(),Tag.begin()+4,"HTTP") == 0)
{
// Evil servers return no version
if (Line[4] == '/')
return true;
}
- if (stringcasecmp(Tag,"Content-Length:"))
+ if (stringcasecmp(Tag,"Content-Length:") == 0)
{
if (Encoding == Closes)
Encoding = Stream;
+ HaveContent = true;
// The length is already set from the Content-Range header
if (StartPos != 0)
return true;
}
- if (stringcasecmp(Tag,"Content-Range:"))
+ if (stringcasecmp(Tag,"Content-Type:") == 0)
+ {
+ HaveContent = true;
+ return true;
+ }
+
+ if (stringcasecmp(Tag,"Content-Range:") == 0)
{
+ HaveContent = true;
+
if (sscanf(Val.c_str(),"bytes %lu-%*u/%lu",&StartPos,&Size) != 2)
return _error->Error("The http server sent an invalid Content-Range header");
if ((unsigned)StartPos > Size)
return true;
}
- if (stringcasecmp(Tag,"Transfer-Encoding:"))
+ if (stringcasecmp(Tag,"Transfer-Encoding:") == 0)
{
- if (stringcasecmp(Val,"chunked"))
+ HaveContent = true;
+ if (stringcasecmp(Val,"chunked") == 0)
Encoding = Chunked;
+
return true;
}
- if (stringcasecmp(Tag,"Last-Modified:"))
+ if (stringcasecmp(Tag,"Last-Modified:") == 0)
{
if (StrToTime(Val,Date) == false)
return _error->Error("Unknown date format");
Req += string("Proxy-Authorization: Basic ") + Base64Encode(ProxyAuth) + "\r\n";*/
Req += "User-Agent: Debian APT-HTTP/1.2\r\n\r\n";
+// cout << Req << endl;
+
Out.Read(Req);
}
/*}}}*/
{
if (Srv->In.Write(File->Fd()) == false)
return _error->Errno("write","Error writing to file");
+ if (Srv->In.IsLimit() == true)
+ return true;
}
if (Srv->In.IsLimit() == true || Srv->Encoding == ServerState::Closes)
{
if (Srv->In.Write(File->Fd()) == false)
return _error->Errno("write","Error writing to the file");
+
+ // Done
+ if (Srv->In.IsLimit() == true)
+ return true;
}
}
to do. Returns
0 - File is open,
1 - IMS hit
- 3 - Unrecoverable error */
+ 3 - Unrecoverable error
+ 4 - Error with error content page */
int HttpMethod::DealWithHeaders(FetchResult &Res,ServerState *Srv)
{
// Not Modified
if (Srv->Result < 200 || Srv->Result >= 300)
{
_error->Error("%u %s",Srv->Result,Srv->Code);
+ if (Srv->HaveContent == true)
+ return 4;
return 3;
}
{
ServerState *Server = 0;
+ int FailCounter = 0;
while (1)
{
+ if (FailCounter >= 2)
+ {
+ Fail("Massive Server Brain Damage");
+ FailCounter = 0;
+ }
+
// We have no commands, wait for some to arrive
if (Queue == 0)
{
}
// Queue the request
- SendReq(Queue,Server->In);
+ SendReq(Queue,Server->Out);
- // Handle the header data
- if (Server->RunHeaders() == false)
+ // Fetch the next URL header data from the server.
+ switch (Server->RunHeaders())
{
- Fail();
- continue;
- }
+ case 0:
+ break;
+
+ // The header data is bad
+ case 2:
+ {
+ _error->Error("Bad header Data");
+ Fail();
+ continue;
+ }
+
+ // The server closed a connection during the header get..
+ default:
+ case 1:
+ {
+ FailCounter++;
+ _error->DumpErrors();
+ Server->Close();
+ continue;
+ }
+ };
// Decide what to do.
FetchResult Res;
// Run the data
if (Server->RunData() == false)
Fail();
-
- Res.MD5Sum = Srv->In.MD5->Result();
+ else
+ {
+ Res.MD5Sum = Server->In.MD5->Result();
+ URIDone(Res);
+ }
+
delete File;
File = 0;
break;
Fail();
break;
}
+
+ // We need to flush the data, the header is like a 404 w/ error text
+ case 4:
+ {
+ Fail();
+
+ // Send to content to dev/null
+ File = new FileFd("/dev/null",FileFd::WriteExists);
+ Server->RunData();
+ delete File;
+ File = 0;
+ break;
+ }
default:
Fail("Internal error");
break;
- }
+ }
+
+ FailCounter = 0;
}
return 0;