| Index: examples/go/http_server.go
|
| diff --git a/examples/go/http_server.go b/examples/go/http_server.go
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0d5eab88b5664e5239e0a4fd31f3897046eaa570
|
| --- /dev/null
|
| +++ b/examples/go/http_server.go
|
| @@ -0,0 +1,247 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package main
|
| +
|
| +import (
|
| + "fmt"
|
| + "log"
|
| + "net"
|
| + "net/http"
|
| + "time"
|
| +
|
| + "golang.org/x/mobile/app"
|
| +
|
| + "mojo/public/go/application"
|
| + "mojo/public/go/bindings"
|
| + "mojo/public/go/system"
|
| +
|
| + "mojo/services/network/public/interfaces/net_address"
|
| + "mojo/services/network/public/interfaces/network_service"
|
| + "mojo/services/network/public/interfaces/tcp_bound_socket"
|
| + "mojo/services/network/public/interfaces/tcp_connected_socket"
|
| + "mojo/services/network/public/interfaces/tcp_server_socket"
|
| +)
|
| +
|
| +//#include "mojo/public/c/system/types.h"
|
| +import "C"
|
| +
|
| +type MojoConnection struct {
|
| + sendStream system.ProducerHandle
|
| + receiveStream system.ConsumerHandle
|
| + socket system.MessagePipeHandle
|
| + localAddr net.Addr
|
| + remoteAddr net.Addr
|
| +}
|
| +
|
| +// Implements net.Conn.
|
| +func (c *MojoConnection) Read(b []byte) (int, error) {
|
| + l := len(b)
|
| + r, read := c.receiveStream.BeginReadData(l, system.MOJO_READ_DATA_FLAG_NONE)
|
| + if r != system.MOJO_RESULT_OK {
|
| + return 0, fmt.Errorf("can't read %v bytes: %v", l, r)
|
| + }
|
| + if l > len(read) {
|
| + l = len(read)
|
| + }
|
| + copy(b, read[:l])
|
| + if r := c.receiveStream.EndReadData(l); r != system.MOJO_RESULT_OK {
|
| + return 0, fmt.Errorf("can't read %v bytes: %v", l, r)
|
| + }
|
| + return l, nil
|
| +}
|
| +
|
| +// Implements net.Conn.
|
| +func (c *MojoConnection) Write(b []byte) (int, error) {
|
| + l := len(b)
|
| + r, buf := c.sendStream.BeginWriteData(l, system.MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)
|
| + if r != system.MOJO_RESULT_OK {
|
| + return 0, fmt.Errorf("can't write %v bytes: %v", l, r)
|
| + }
|
| + copy(buf, b)
|
| + if r := c.sendStream.EndWriteData(l); r != system.MOJO_RESULT_OK {
|
| + return 0, fmt.Errorf("can't write %v bytes: %v", l, r)
|
| + }
|
| + return l, nil
|
| +}
|
| +
|
| +// Implements net.Conn.
|
| +func (c *MojoConnection) Close() error {
|
| + c.sendStream.Close()
|
| + c.receiveStream.Close()
|
| + c.socket.Close()
|
| + return nil
|
| +}
|
| +
|
| +// Implements net.Conn.
|
| +func (c *MojoConnection) LocalAddr() net.Addr {
|
| + return c.localAddr
|
| +}
|
| +
|
| +// Implements net.Conn.
|
| +func (c *MojoConnection) RemoteAddr() net.Addr {
|
| + return c.remoteAddr
|
| +}
|
| +
|
| +// Implements net.Conn.
|
| +func (c *MojoConnection) SetDeadline(t time.Time) error {
|
| + if err := c.SetReadDeadline(t); err != nil {
|
| + return err
|
| + }
|
| + return c.SetWriteDeadline(t)
|
| +}
|
| +
|
| +// Implements net.Conn.
|
| +func (c *MojoConnection) SetReadDeadline(t time.Time) error {
|
| + // Do nothing.
|
| + return nil
|
| +}
|
| +
|
| +// Implements net.Conn.
|
| +func (c *MojoConnection) SetWriteDeadline(t time.Time) error {
|
| + // Do nothing.
|
| + return nil
|
| +}
|
| +
|
| +type MojoListener struct {
|
| + serverSocket *tcp_server_socket.TcpServerSocketProxy
|
| +}
|
| +
|
| +// 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
|
| +}
|
| +
|
| +// Implements net.Listener.
|
| +func (l *MojoListener) Close() error {
|
| + l.serverSocket.Close_proxy()
|
| + return nil
|
| +}
|
| +
|
| +// Implements net.Listener.
|
| +func (l *MojoListener) Addr() net.Addr {
|
| + return &net.TCPAddr{
|
| + IP: []byte{127, 0, 0, 1},
|
| + Port: 8080,
|
| + }
|
| +}
|
| +
|
| +type HttpServerDelegate struct {
|
| + networkService *network_service.NetworkServiceProxy
|
| + tcpBoundSocket *tcp_bound_socket.TcpBoundSocketProxy
|
| + serverSocket *tcp_server_socket.TcpServerSocketProxy
|
| +}
|
| +
|
| +func (d *HttpServerDelegate) InitTCPBoundSocket() error {
|
| + addr := &net_address.NetAddress{
|
| + net_address.NetAddressFamily_IpV4,
|
| + &net_address.NetAddressIPv4{
|
| + 8080,
|
| + [4]uint8{127, 0, 0, 1},
|
| + },
|
| + nil,
|
| + }
|
| + request, pointer := tcp_bound_socket.CreateMessagePipeForTcpBoundSocket()
|
| + networkError, _, err := d.networkService.CreateTcpBoundSocket(addr, request)
|
| + if err != nil {
|
| + return err
|
| + }
|
| + if networkError.Code != 0 {
|
| + return fmt.Errorf("%s", *networkError.Description)
|
| + }
|
| + d.tcpBoundSocket = tcp_bound_socket.NewTcpBoundSocketProxy(pointer, bindings.GetAsyncWaiter())
|
| + return nil
|
| +}
|
| +
|
| +func (d *HttpServerDelegate) InitServerSocket() error {
|
| + request, pointer := tcp_server_socket.CreateMessagePipeForTcpServerSocket()
|
| + networkError, err := d.tcpBoundSocket.StartListening(request)
|
| + if err != nil {
|
| + return err
|
| + }
|
| + if networkError.Code != 0 {
|
| + return fmt.Errorf("%s", *networkError.Description)
|
| + }
|
| + d.serverSocket = tcp_server_socket.NewTcpServerSocketProxy(pointer, bindings.GetAsyncWaiter())
|
| + return nil
|
| +}
|
| +
|
| +func (d *HttpServerDelegate) Initialize(ctx application.Context) {
|
| + request, pointer := network_service.CreateMessagePipeForNetworkService()
|
| + ctx.ConnectToApplication("mojo:network_service").ConnectToService(&request)
|
| + d.networkService = network_service.NewNetworkServiceProxy(pointer, bindings.GetAsyncWaiter())
|
| +
|
| + if err := d.InitTCPBoundSocket(); err != nil {
|
| + log.Printf("can't create TCP socket: %v\n", err)
|
| + return
|
| + }
|
| + if err := d.InitServerSocket(); err != nil {
|
| + log.Printf("can't create server socket: %v\n", err)
|
| + return
|
| + }
|
| +
|
| + http.HandleFunc("/go", func(w http.ResponseWriter, r *http.Request) {
|
| + fmt.Fprintf(w, "Hello, Go http server!")
|
| + })
|
| + l := &MojoListener{d.serverSocket}
|
| + if err := http.Serve(l, nil); err != nil {
|
| + log.Printf("can't serve request: %v\n", err)
|
| + return
|
| + }
|
| +}
|
| +
|
| +func (d *HttpServerDelegate) AcceptConnection(c *application.Connection) {
|
| + c.Close()
|
| +}
|
| +
|
| +func (d *HttpServerDelegate) Quit() {
|
| + d.networkService.Close_proxy()
|
| + d.tcpBoundSocket.Close_proxy()
|
| + d.serverSocket.Close_proxy()
|
| +}
|
| +
|
| +//export MojoMain
|
| +func MojoMain(handle C.MojoHandle) C.MojoResult {
|
| + application.Run(&HttpServerDelegate{}, system.MojoHandle(handle))
|
| + return C.MOJO_RESULT_OK
|
| +}
|
| +
|
| +func main() {
|
| + app.Run(app.Callbacks{})
|
| +}
|
|
|