// CreateMessagePipeForInterface creates a message pipe with interface request // on one end and interface pointer on the other end. The interface request // should be attached to appropriate mojo interface implementation and // the interface pointer should be attached to mojo interface proxy. func CreateMessagePipeForMojoInterface() (InterfaceRequest, InterfacePointer) { r, h0, h1 := system.GetCore().CreateMessagePipe(nil) if r != system.MOJO_RESULT_OK { panic(fmt.Sprintf("can't create a message pipe: %v", r)) } return InterfaceRequest{MessagePipeHandleOwner{h0}}, InterfacePointer{MessagePipeHandleOwner{h1}} }
// newAsyncWaiter creates an asyncWaiterImpl and starts its worker goroutine. func newAsyncWaiter() *asyncWaiterImpl { result, h0, h1 := system.GetCore().CreateMessagePipe(nil) if result != system.MOJO_RESULT_OK { panic(fmt.Sprintf("can't create message pipe %v", result)) } waitChan := make(chan waitRequest, 10) cancelChan := make(chan AsyncWaitId, 10) isNotified := new(int32) worker := &asyncWaiterWorker{ []system.Handle{h1}, []system.MojoHandleSignals{system.MOJO_HANDLE_SIGNAL_READABLE}, []AsyncWaitId{0}, []chan<- WaitResponse{make(chan WaitResponse)}, isNotified, waitChan, cancelChan, 0, } runtime.SetFinalizer(worker, finalizeWorker) go worker.runLoop() waiter := &asyncWaiterImpl{ wakingHandle: h0, isWorkerNotified: isNotified, waitChan: waitChan, cancelChan: cancelChan, } runtime.SetFinalizer(waiter, finalizeAsyncWaiter) return waiter }
// runLoop run loop of the asyncWaiterWorker. Blocks on |WaitMany()|. If the // wait is interrupted by waking handle (index 0) then it means that the worker // was woken by waiterImpl, so the worker processes incoming requests from // waiterImpl; otherwise responses to corresponding wait request. func (w *asyncWaiterWorker) runLoop() { for { result, index, states := system.GetCore().WaitMany(w.handles, w.signals, system.MOJO_DEADLINE_INDEFINITE) // Set flag to 0, so that the next incoming request to // waiterImpl would explicitly wake worker by sending a message // to waking message pipe. atomic.StoreInt32(w.isNotified, 0) if index == -1 { panic(fmt.Sprintf("error waiting on handles: %v", result)) break } // Zero index means that the worker was signaled by asyncWaiterImpl. if index == 0 { if result != system.MOJO_RESULT_OK { panic(fmt.Sprintf("error waiting on waking handle: %v", result)) } w.handles[0].(system.MessagePipeHandle).ReadMessage(system.MOJO_READ_MESSAGE_FLAG_NONE) w.processIncomingRequests() } else if result != system.MOJO_RESULT_OK { w.sendWaitResponseAndRemove(index, result, system.MojoHandleSignalsState{}) } else { w.respondToSatisfiedWaits(states) } } }
// Implements net.Listener. func (l *MojoListener) Accept() (net.Conn, error) { r, sendProducer, sendConsumer := system.GetCore().CreateDataPipe(nil) if r != system.MOJO_RESULT_OK { panic(fmt.Sprintf("can't create data pipe: %v", r)) } r, receiveProducer, receiveConsumer := system.GetCore().CreateDataPipe(nil) if r != system.MOJO_RESULT_OK { panic(fmt.Sprintf("can't create data pipe: %v", r)) } request, pointer := tcp_connected_socket.CreateMessagePipeForTcpConnectedSocket() networkError, remoteAddress, err := l.serverSocket.Accept(sendConsumer, receiveProducer, request) if err != nil { return nil, err } if networkError.Code != 0 { return nil, fmt.Errorf("%s", *networkError.Description) } var addr net.Addr if remoteAddress.Ipv4 != nil { addr = &net.TCPAddr{ IP: remoteAddress.Ipv4.Addr[:4], Port: int(remoteAddress.Ipv4.Port), } } else { addr = &net.TCPAddr{ IP: remoteAddress.Ipv6.Addr[:16], Port: int(remoteAddress.Ipv6.Port), } } return &MojoConnection{ sendProducer, receiveConsumer, pointer.PassMessagePipe(), l.Addr(), addr, }, nil }
func (u *mupdate) GetAttachment(name string) (system.ConsumerHandle, error) { r, producer, consumer := system.GetCore().CreateDataPipe(nil) if r != system.MOJO_RESULT_OK { return nil, fmt.Errorf("can't create data pipe: %v", r) } go func() { defer producer.Close() dataOrErr := <-u.u.Attachment(u.ctx, name) if dataOrErr.Error != nil { u.ctx.Error(dataOrErr.Error) } else { producer.WriteData([]byte(dataOrErr.Data), system.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE) } }() return consumer, nil }
// Run binds your mojo application to provided message pipe handle and runs it // until the application is terminated. func Run(delegate Delegate, applicationRequest system.MojoHandle) { messagePipe := system.GetCore().AcquireNativeHandle(applicationRequest).ToMessagePipeHandle() appRequest := application.Application_Request{bindings.NewMessagePipeHandleOwner(messagePipe)} impl := &ApplicationImpl{ delegate: delegate, } stub := application.NewApplicationStub(appRequest, impl, bindings.GetAsyncWaiter()) impl.runner = stub for { if err := stub.ServeRequest(); err != nil { connectionError, ok := err.(*bindings.ConnectionError) if !ok || !connectionError.Closed() { log.Println(err) } impl.RequestQuit() break } } }
func (h *HttpHandler) HandleRequest(request http_request.HttpRequest) (http_response.HttpResponse, error) { resp := "Hello, Go http handler!" r, producer, consumer := system.GetCore().CreateDataPipe(&system.DataPipeOptions{ system.MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, 1, uint32(len(resp)), }) if r != system.MOJO_RESULT_OK { panic(fmt.Sprintf("can't create data pipe: %v", r)) } producer.WriteData([]byte(resp), system.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE) producer.Close() return http_response.HttpResponse{ 200, &consumer, int64(len(resp)), "text/html; charset=utf-8", nil, }, nil }
func init() { embedder.InitializeMojoEmbedder() core = system.GetCore() waiter = bindings.GetAsyncWaiter() }