Miro Kuratczyk 7 лет назад
Родитель
Сommit
e20d01ec95
2 измененных файлов с 101 добавлено и 19 удалено
  1. 68 19
      MeasurementLibrary/PsiphonTunnel.go
  2. 33 0
      MeasurementLibrary/example/PsiphonTunnel.h

+ 68 - 19
MeasurementLibrary/PsiphonTunnel.go

@@ -47,13 +47,40 @@ type MeasurementTest struct {
 var measurementTest MeasurementTest
 var measurementTest MeasurementTest
 
 
 //export Start
 //export Start
+// Start starts the controller and returns once either of the following has occured: an active tunnel has been
+// established, the timeout has elapsed before an active tunnel could be established or an error has occured.
+//
+// Start returns a StartResult object serialized as a JSON string in the form of a null-terminated buffer of C chars.
+// Start will return,
+// On success:
+//   {
+//     "result_code": 0,
+//     "bootstrap_time": <time_to_establish_tunnel>,
+//     "http_proxy_port": <http_proxy_port_num>,
+//     "socks_proxy_port": <socks_proxy_port_num>
+//   }
+//
+// On timeout:
+//  {
+//    "result_code": 1,
+//    "error": <error message>
+//  }
+//
+// On other error:
+//   {
+//     "result_code": 2,
+//     "error": <error message>
+//   }
+//
+// networkID should be not be blank and should follow the format specified by
+// https://godoc.org/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon#NetworkIDGetter.
 func Start(configJSON, embeddedServerEntryList, networkID string, timeout int64) *C.char {
 func Start(configJSON, embeddedServerEntryList, networkID string, timeout int64) *C.char {
 
 
 	// Load provided config
 	// Load provided config
 
 
 	config, err := psiphon.LoadConfig([]byte(configJSON))
 	config, err := psiphon.LoadConfig([]byte(configJSON))
 	if err != nil {
 	if err != nil {
-		return errorJSONForC(err)
+		return startErrorJson(err)
 	}
 	}
 
 
 	// Set network ID
 	// Set network ID
@@ -66,7 +93,7 @@ func Start(configJSON, embeddedServerEntryList, networkID string, timeout int64)
 
 
 	err = config.Commit()
 	err = config.Commit()
 	if err != nil {
 	if err != nil {
-		return errorJSONForC(err)
+		return startErrorJson(err)
 	}
 	}
 
 
 	// Setup signals
 	// Setup signals
@@ -112,7 +139,7 @@ func Start(configJSON, embeddedServerEntryList, networkID string, timeout int64)
 
 
 	err = psiphon.InitDataStore(config)
 	err = psiphon.InitDataStore(config)
 	if err != nil {
 	if err != nil {
-		return errorJSONForC(err)
+		return startErrorJson(err)
 	}
 	}
 
 
 	// Store embedded server entries
 	// Store embedded server entries
@@ -122,19 +149,19 @@ func Start(configJSON, embeddedServerEntryList, networkID string, timeout int64)
 		common.GetCurrentTimestamp(),
 		common.GetCurrentTimestamp(),
 		protocol.SERVER_ENTRY_SOURCE_EMBEDDED)
 		protocol.SERVER_ENTRY_SOURCE_EMBEDDED)
 	if err != nil {
 	if err != nil {
-		return errorJSONForC(err)
+		return startErrorJson(err)
 	}
 	}
 
 
 	err = psiphon.StoreServerEntries(config, serverEntries, false)
 	err = psiphon.StoreServerEntries(config, serverEntries, false)
 	if err != nil {
 	if err != nil {
-		return errorJSONForC(err)
+		return startErrorJson(err)
 	}
 	}
 
 
 	// Run Psiphon
 	// Run Psiphon
 
 
 	controller, err := psiphon.NewController(config)
 	controller, err := psiphon.NewController(config)
 	if err != nil {
 	if err != nil {
-		return errorJSONForC(err)
+		return startErrorJson(err)
 	}
 	}
 
 
 	measurementTest.controllerCtx, measurementTest.stopController = context.WithCancel(context.Background())
 	measurementTest.controllerCtx, measurementTest.stopController = context.WithCancel(context.Background())
@@ -163,12 +190,9 @@ func Start(configJSON, embeddedServerEntryList, networkID string, timeout int64)
 		case testError <- errors.New("controller.Run exited unexpectedly"):
 		case testError <- errors.New("controller.Run exited unexpectedly"):
 		default:
 		default:
 		}
 		}
-
-		// This is a noop if stopController was already called
-		measurementTest.stopController()
 	}()
 	}()
 
 
-	// Wait for a stop signal, then stop Psiphon and exit
+	// Wait for an active tunnel, timeout or error
 
 
 	select {
 	select {
 	case <-connected:
 	case <-connected:
@@ -191,15 +215,14 @@ func Start(configJSON, embeddedServerEntryList, networkID string, timeout int64)
 
 
 	// Return result
 	// Return result
 
 
-	resultJSON, err := json.Marshal(result)
-	if err != nil {
-		return errorJSONForC(err)
-	}
-
-	return C.CString(string(resultJSON))
+	return marshalStartResult(result)
 }
 }
 
 
 //export Stop
 //export Stop
+// Stop stops the controller if it is running and waits for it to clean up and exit.
+//
+// Stop should always be called after a successful call to Start to ensure the
+// controller is not left running.
 func Stop() {
 func Stop() {
 	if measurementTest.stopController != nil {
 	if measurementTest.stopController != nil {
 		measurementTest.stopController()
 		measurementTest.stopController()
@@ -207,13 +230,39 @@ func Stop() {
 	measurementTest.controllerWaitGroup.Wait()
 	measurementTest.controllerWaitGroup.Wait()
 }
 }
 
 
+// secondsBeforeNow returns the delta seconds of the current time subtract startTime.
 func secondsBeforeNow(startTime time.Time) float64 {
 func secondsBeforeNow(startTime time.Time) float64 {
 	delta := time.Now().Sub(startTime)
 	delta := time.Now().Sub(startTime)
 	return delta.Seconds()
 	return delta.Seconds()
 }
 }
 
 
-func errorJSONForC(err error) *C.char {
-	return C.CString(fmt.Sprintf("{\"error\": \"%s\"}", err.Error()))
+// marshalStartResult serializes a StartResult object as a JSON string in the form
+// of a null-terminated buffer of C chars.
+func marshalStartResult(result StartResult) *C.char {
+	resultJSON, err := json.Marshal(result)
+	if err != nil {
+		return C.CString(fmt.Sprintf("{\"result_code\":%d, \"error\": \"%s\"}", StartResultCodeOtherError, err.Error()))
+	}
+
+	return C.CString(string(resultJSON))
+}
+
+// startErrorJson returns a StartResult object serialized as a JSON string in the form
+// of a null-terminated buffer of C chars. The object's return result code will be set to
+// StartResultCodeOtherError (2) and its error string set to the error string of the provided error.
+//
+// The JSON will be in the form of:
+// {
+//   "result_code": 2,
+//   "error": <error message>
+// }
+func startErrorJson(err error) *C.char {
+	var result StartResult
+	result.Code = StartResultCodeOtherError
+	result.ErrorString = err.Error()
+
+	return marshalStartResult(result)
 }
 }
 
 
-func main() {} // stub required by cgo
+// main is a stub required by cgo.
+func main() {}

+ 33 - 0
MeasurementLibrary/example/PsiphonTunnel.h

@@ -53,8 +53,41 @@ extern "C" {
 #endif
 #endif
 
 
 
 
+// Start starts the controller and returns once either of the following has occured: an active tunnel has been
+// established, the timeout has elapsed before an active tunnel could be established or an error has occured.
+//
+// Start returns a StartResult object serialized as a JSON string in the form of a null-terminated buffer of C chars.
+// Start will return,
+// On success:
+//   {
+//     "result_code": 0,
+//     "bootstrap_time": <time_to_establish_tunnel>,
+//     "http_proxy_port": <http_proxy_port_num>,
+//     "socks_proxy_port": <socks_proxy_port_num>
+//   }
+//
+// On timeout:
+//  {
+//    "result_code": 1,
+//    "error": <error message>
+//  }
+//
+// On other error:
+//   {
+//     "result_code": 2,
+//     "error": <error message>
+//   }
+//
+// networkID should be not be blank and should follow the format specified by
+// https://godoc.org/github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon#NetworkIDGetter.
+
 extern char* Start(GoString p0, GoString p1, GoString p2, GoInt64 p3);
 extern char* Start(GoString p0, GoString p1, GoString p2, GoInt64 p3);
 
 
+// Stop stops the controller if it is running and waits for it to clean up and exit.
+//
+// Stop should always be called after a successful call to Start to ensure the
+// controller is not left running.
+
 extern void Stop();
 extern void Stop();
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus