Просмотр исходного кода

Merge pull request #283 from rod-hynes/master

psiphond bug fixes
Rod Hynes 9 лет назад
Родитель
Сommit
a53dfb9ded
3 измененных файлов с 39 добавлено и 14 удалено
  1. 24 8
      psiphon/server/geoip.go
  2. 2 2
      psiphon/server/meek.go
  3. 13 4
      psiphon/server/tunnelServer.go

+ 24 - 8
psiphon/server/geoip.go

@@ -175,21 +175,37 @@ func (geoIP *GeoIPService) Lookup(ipAddress string) GeoIPData {
 	return result
 	return result
 }
 }
 
 
+// SetSessionCache adds the sessionID/geoIPData pair to the
+// session cache. This value will not expire; the caller must
+// call MarkSessionCacheToExpire to initiate expiry.
+// Calling SetSessionCache for an existing sessionID will
+// replace the previous value and reset any expiry.
 func (geoIP *GeoIPService) SetSessionCache(sessionID string, geoIPData GeoIPData) {
 func (geoIP *GeoIPService) SetSessionCache(sessionID string, geoIPData GeoIPData) {
-	geoIP.sessionCache.Set(sessionID, geoIPData, cache.DefaultExpiration)
+	geoIP.sessionCache.Set(sessionID, geoIPData, cache.NoExpiration)
 }
 }
 
 
-func (geoIP *GeoIPService) GetSessionCache(
-	sessionID string) GeoIPData {
+// MarkSessionCacheToExpire initiates expiry for an existing
+// session cache entry, if the session ID is found in the cache.
+// Concurrency note: SetSessionCache and MarkSessionCacheToExpire
+// should not be called concurrently for a single session ID.
+func (geoIP *GeoIPService) MarkSessionCacheToExpire(sessionID string) {
+	geoIPData, found := geoIP.sessionCache.Get(sessionID)
+	// Note: potential race condition between Get and Set. In practice,
+	// the tunnel server won't clobber a SetSessionCache value by calling
+	// MarkSessionCacheToExpire concurrently.
+	if found {
+		geoIP.sessionCache.Set(sessionID, geoIPData, cache.DefaultExpiration)
+	}
+}
+
+// GetSessionCache returns the cached GeoIPData for the
+// specified session ID; a blank GeoIPData is returned
+// if the session ID is not found in the cache.
+func (geoIP *GeoIPService) GetSessionCache(sessionID string) GeoIPData {
 	geoIPData, found := geoIP.sessionCache.Get(sessionID)
 	geoIPData, found := geoIP.sessionCache.Get(sessionID)
 	if !found {
 	if !found {
 		return NewGeoIPData()
 		return NewGeoIPData()
 	}
 	}
-	// Extend the TTL for this item. If this fails, the cache entry
-	// value remains the same but the TTL is not extended.
-	// Note: sessionCache.Replace can clobber sessionCache.Set changes,
-	// but this is not a concern in practise.
-	_ = geoIP.sessionCache.Replace(sessionID, geoIPData, cache.DefaultExpiration)
 	return geoIPData.(GeoIPData)
 	return geoIPData.(GeoIPData)
 }
 }
 
 

+ 2 - 2
psiphon/server/meek.go

@@ -709,8 +709,8 @@ func (conn *meekConn) pumpWrites(writer io.Writer) error {
 				return err
 				return err
 			}
 			}
 
 
-			if conn.protocolVersion < MEEK_PROTOCOL_VERSION_2 {
-				// Protocol v1 clients expect at most
+			if conn.protocolVersion < MEEK_PROTOCOL_VERSION_1 {
+				// Pre-protocol version 1 clients expect at most
 				// MEEK_MAX_PAYLOAD_LENGTH response bodies
 				// MEEK_MAX_PAYLOAD_LENGTH response bodies
 				return nil
 				return nil
 			}
 			}

+ 13 - 4
psiphon/server/tunnelServer.go

@@ -778,10 +778,12 @@ func (sshClient *sshClient) passwordCallback(conn ssh.ConnMetadata, password []b
 	geoIPData := sshClient.geoIPData
 	geoIPData := sshClient.geoIPData
 	sshClient.Unlock()
 	sshClient.Unlock()
 
 
-	// Store the GeoIP data associated with the session ID. This makes the GeoIP data
-	// available to the web server for web transport Psiphon API requests. To allow for
-	// post-tunnel final status requests, the lifetime of cached GeoIP records exceeds
-	// the lifetime of the sshClient, and that's why this distinct session cache exists.
+	// Store the GeoIP data associated with the session ID. This makes
+	// the GeoIP data available to the web server for web API requests.
+	// A cache that's distinct from the sshClient record is used to allow
+	// for or post-tunnel final status requests.
+	// If the client is reconnecting with the same session ID, this call
+	// will undo the expiry set by MarkSessionCacheToExpire.
 	sshClient.sshServer.support.GeoIPService.SetSessionCache(sessionID, geoIPData)
 	sshClient.sshServer.support.GeoIPService.SetSessionCache(sessionID, geoIPData)
 
 
 	return nil, nil
 	return nil, nil
@@ -862,8 +864,15 @@ func (sshClient *sshClient) stop() {
 	logFields["peak_concurrent_port_forward_count_udp"] = sshClient.udpTrafficState.peakConcurrentPortForwardCount
 	logFields["peak_concurrent_port_forward_count_udp"] = sshClient.udpTrafficState.peakConcurrentPortForwardCount
 	logFields["total_port_forward_count_udp"] = sshClient.udpTrafficState.totalPortForwardCount
 	logFields["total_port_forward_count_udp"] = sshClient.udpTrafficState.totalPortForwardCount
 
 
+	sessionID := sshClient.sessionID
+
 	sshClient.Unlock()
 	sshClient.Unlock()
 
 
+	// Initiate cleanup of the GeoIP session cache. To allow for post-tunnel
+	// final status requests, the lifetime of cached GeoIP records exceeds the
+	// lifetime of the sshClient.
+	sshClient.sshServer.support.GeoIPService.MarkSessionCacheToExpire(sessionID)
+
 	log.LogRawFieldsWithTimestamp(logFields)
 	log.LogRawFieldsWithTimestamp(logFields)
 }
 }