]> git.ipfire.org Git - thirdparty/squid.git/blame - src/mgr/StoreToCommWriter.cc
Send HTTP/1.1 on CONNECT responses
[thirdparty/squid.git] / src / mgr / StoreToCommWriter.cc
CommitLineData
8822ebee
AR
1/*
2 * $Id$
3 *
4 * DEBUG: section 16 Cache Manager API
5 *
6 */
7
8#include "config.h"
9#include "base/TextException.h"
10#include "CommCalls.h"
11#include "ipc/FdNotes.h"
12#include "mgr/StoreToCommWriter.h"
13#include "StoreClient.h"
14#include "Store.h"
15
16
17CBDATA_NAMESPACED_CLASS_INIT(Mgr, StoreToCommWriter);
18
19
20Mgr::StoreToCommWriter::StoreToCommWriter(int aFd, StoreEntry* anEntry):
d9fc6862
A
21 AsyncJob("Mgr::StoreToCommWriter"),
22 fd(aFd), entry(anEntry), sc(NULL), writeOffset(0), closer(NULL)
8822ebee
AR
23{
24 debugs(16, 6, HERE << "FD " << fd);
25 closer = asyncCall(16, 5, "Mgr::StoreToCommWriter::noteCommClosed",
d9fc6862 26 CommCbMemFunT<StoreToCommWriter, CommCloseCbParams>(this, &StoreToCommWriter::noteCommClosed));
8822ebee
AR
27 comm_add_close_handler(fd, closer);
28}
29
30Mgr::StoreToCommWriter::~StoreToCommWriter()
31{
32 debugs(16, 6, HERE);
33 assert(!entry);
34 assert(!sc);
35 close();
36}
37
38/// closes our copy of the client HTTP connection socket
39void
40Mgr::StoreToCommWriter::close()
41{
42 if (fd >= 0) {
43 if (closer != NULL) {
44 comm_remove_close_handler(fd, closer);
45 closer = NULL;
46 }
47 comm_close(fd);
48 fd = -1;
49 }
50}
51
52void
53Mgr::StoreToCommWriter::start()
54{
55 debugs(16, 6, HERE);
56 Must(fd >= 0);
57 Must(entry != NULL);
58 entry->registerAbort(&StoreToCommWriter::Abort, this);
59 sc = storeClientListAdd(entry, this);
60 Must(sc != NULL);
61
62 // initiate the receive-from-store, write-to-comm sequence
63 scheduleStoreCopy();
64}
65
66void
67Mgr::StoreToCommWriter::scheduleStoreCopy()
68{
69 debugs(16, 6, HERE);
70 Must(entry != NULL);
71 Must(sc != NULL);
72 StoreIOBuffer readBuf(sizeof(buffer), writeOffset, buffer);
73 storeClientCopy(sc, entry, readBuf, &NoteStoreCopied, this);
74}
75
76void
77Mgr::StoreToCommWriter::NoteStoreCopied(void* data, StoreIOBuffer ioBuf)
78{
79 Must(data != NULL);
80 // make sync Store call async to get async call protections and features
81 StoreToCommWriter* writer = static_cast<StoreToCommWriter*>(data);
82 typedef UnaryMemFunT<StoreToCommWriter, StoreIOBuffer> MyDialer;
83 AsyncCall::Pointer call =
84 asyncCall(16, 5, "Mgr::StoreToCommWriter::noteStoreCopied",
d9fc6862 85 MyDialer(writer, &StoreToCommWriter::noteStoreCopied, ioBuf));
8822ebee
AR
86 ScheduleCallHere(call);
87}
88
89void
90Mgr::StoreToCommWriter::noteStoreCopied(StoreIOBuffer ioBuf)
91{
92 debugs(16, 6, HERE);
93 Must(!ioBuf.flags.error);
94 if (ioBuf.length > 0)
95 scheduleCommWrite(ioBuf); // write received action results to client
96 else
97 Must(doneAll()); // otherwise, why would Store call us with no data?
98}
99
100void
101Mgr::StoreToCommWriter::scheduleCommWrite(const StoreIOBuffer& ioBuf)
102{
103 debugs(16, 6, HERE);
104 Must(fd >= 0);
105 Must(ioBuf.data != NULL);
106 // write filled buffer
107 typedef CommCbMemFunT<StoreToCommWriter, CommIoCbParams> MyDialer;
108 AsyncCall::Pointer writer =
109 asyncCall(16, 5, "Mgr::StoreToCommWriter::noteCommWrote",
d9fc6862 110 MyDialer(this, &StoreToCommWriter::noteCommWrote));
8822ebee
AR
111 comm_write(fd, ioBuf.data, ioBuf.length, writer);
112}
113
114void
115Mgr::StoreToCommWriter::noteCommWrote(const CommIoCbParams& params)
116{
117 debugs(16, 6, HERE);
118 Must(params.flag == COMM_OK);
119 Must(params.fd == fd);
120 Must(params.size != 0);
121 writeOffset += params.size;
122 if (!doneAll())
123 scheduleStoreCopy(); // retrieve the next data portion
124}
125
126void
127Mgr::StoreToCommWriter::noteCommClosed(const CommCloseCbParams& params)
128{
129 debugs(16, 6, HERE);
130 Must(fd == params.fd);
131 fd = -1;
132 mustStop("commClosed");
133}
134
135void
136Mgr::StoreToCommWriter::swanSong()
137{
138 debugs(16, 6, HERE);
139 if (entry != NULL) {
140 if (sc != NULL) {
141 storeUnregister(sc, entry, this);
142 sc = NULL;
143 }
144 entry->unregisterAbort();
145 entry->unlock();
146 entry = NULL;
147 }
148 close();
149}
150
151bool
152Mgr::StoreToCommWriter::doneAll() const
153{
154 return entry &&
d9fc6862
A
155 entry->store_status == STORE_OK && // the action is over
156 writeOffset >= entry->objectLen(); // we wrote all the results
8822ebee
AR
157}
158
159void
160Mgr::StoreToCommWriter::Abort(void* param)
161{
162 StoreToCommWriter* mgrWriter = static_cast<StoreToCommWriter*>(param);
163 if (mgrWriter->fd >= 0)
164 comm_close(mgrWriter->fd);
165}
166
167
168int
169Mgr::ImportHttpFdIntoComm(int fd)
170{
171 struct sockaddr_in addr;
172 socklen_t len = sizeof(addr);
173 if (getsockname(fd, reinterpret_cast<sockaddr*>(&addr), &len) == 0) {
174 Ip::Address ipAddr(addr);
175 struct addrinfo* addr_info = NULL;
176 ipAddr.GetAddrInfo(addr_info);
177 addr_info->ai_socktype = SOCK_STREAM;
178 addr_info->ai_protocol = IPPROTO_TCP;
179 comm_import_opened(fd, ipAddr, COMM_NONBLOCKING, Ipc::FdNote(Ipc::fdnHttpSocket), addr_info);
180 ipAddr.FreeAddrInfo(addr_info);
181 } else {
182 debugs(16, DBG_CRITICAL, HERE << "ERROR: FD " << fd << ' ' << xstrerror());
183 ::close(fd);
184 fd = -1;
185 }
186 return fd;
187}