|
|
@@ -103,6 +103,19 @@ public class UploadPack { |
|
|
|
/** Timeout in seconds to wait for client interaction. */ |
|
|
|
private int timeout; |
|
|
|
|
|
|
|
/** |
|
|
|
* Is the client connection a bi-directional socket or pipe? |
|
|
|
* <p> |
|
|
|
* If true, this class assumes it can perform multiple read and write cycles |
|
|
|
* with the client over the input and output streams. This matches the |
|
|
|
* functionality available with a standard TCP/IP connection, or a local |
|
|
|
* operating system or in-memory pipe. |
|
|
|
* <p> |
|
|
|
* If false, this class runs in a read everything then output results mode, |
|
|
|
* making it suitable for single round-trip systems RPCs such as HTTP. |
|
|
|
*/ |
|
|
|
private boolean biDirectionalPipe = true; |
|
|
|
|
|
|
|
/** Timer to manage {@link #timeout}. */ |
|
|
|
private InterruptTimer timer; |
|
|
|
|
|
|
@@ -198,6 +211,27 @@ public class UploadPack { |
|
|
|
timeout = seconds; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @return true if this class expects a bi-directional pipe opened between |
|
|
|
* the client and itself. The default is true. |
|
|
|
*/ |
|
|
|
public boolean isBiDirectionalPipe() { |
|
|
|
return biDirectionalPipe; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @param twoWay |
|
|
|
* if true, this class will assume the socket is a fully |
|
|
|
* bidirectional pipe between the two peers and takes advantage |
|
|
|
* of that by first transmitting the known refs, then waiting to |
|
|
|
* read commands. If false, this class assumes it must read the |
|
|
|
* commands before writing output and does not perform the |
|
|
|
* initial advertising. |
|
|
|
*/ |
|
|
|
public void setBiDirectionalPipe(final boolean twoWay) { |
|
|
|
biDirectionalPipe = twoWay; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Execute the upload task on the socket. |
|
|
|
* |
|
|
@@ -247,7 +281,19 @@ public class UploadPack { |
|
|
|
} |
|
|
|
|
|
|
|
private void service() throws IOException { |
|
|
|
sendAdvertisedRefs(); |
|
|
|
if (biDirectionalPipe) |
|
|
|
sendAdvertisedRefs(); |
|
|
|
else { |
|
|
|
refs = db.getAllRefs(); |
|
|
|
for (Ref r : refs.values()) { |
|
|
|
try { |
|
|
|
walk.parseAny(r.getObjectId()).add(ADVERTISED); |
|
|
|
} catch (IOException e) { |
|
|
|
// Skip missing/corrupt objects |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
recvWants(); |
|
|
|
if (wantAll.isEmpty()) |
|
|
|
return; |
|
|
@@ -259,8 +305,8 @@ public class UploadPack { |
|
|
|
else |
|
|
|
multiAck = MultiAck.OFF; |
|
|
|
|
|
|
|
negotiate(); |
|
|
|
sendPack(); |
|
|
|
if (negotiate()) |
|
|
|
sendPack(); |
|
|
|
} |
|
|
|
|
|
|
|
private void sendAdvertisedRefs() throws IOException { |
|
|
@@ -336,7 +382,7 @@ public class UploadPack { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void negotiate() throws IOException { |
|
|
|
private boolean negotiate() throws IOException { |
|
|
|
ObjectId last = ObjectId.zeroId(); |
|
|
|
for (;;) { |
|
|
|
String line; |
|
|
@@ -350,6 +396,9 @@ public class UploadPack { |
|
|
|
if (commonBase.isEmpty() || multiAck != MultiAck.OFF) |
|
|
|
pckOut.writeString("NAK\n"); |
|
|
|
pckOut.flush(); |
|
|
|
if (!biDirectionalPipe) |
|
|
|
return false; |
|
|
|
|
|
|
|
} else if (line.startsWith("have ") && line.length() == 45) { |
|
|
|
final ObjectId id = ObjectId.fromString(line.substring(5)); |
|
|
|
if (matchHave(id)) { |
|
|
@@ -389,7 +438,8 @@ public class UploadPack { |
|
|
|
|
|
|
|
else if (multiAck != MultiAck.OFF) |
|
|
|
pckOut.writeString("ACK " + last.name() + "\n"); |
|
|
|
break; |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} else { |
|
|
|
throw new PackProtocolException("expected have; got " + line); |